@adminforth/i18n 1.0.21-next.0 β 1.0.21
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 +6 -0
- package/dist/index.js +63 -42
- package/index.ts +71 -51
- package/package.json +1 -1
package/Changelog.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [1.0.21] - next
|
|
9
9
|
|
|
10
|
+
### Fixed
|
|
11
|
+
- improve cache reset when editing messages manually
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Translating external app" feature by using feedCategoryTranslations
|
|
15
|
+
|
|
10
16
|
## [1.0.20]
|
|
11
17
|
|
|
12
18
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -215,7 +215,6 @@ export default class I18N extends AdminForthPlugin {
|
|
|
215
215
|
}));
|
|
216
216
|
// add hook on edit of any translation
|
|
217
217
|
resourceConfig.hooks.edit.afterSave.push((_d) => __awaiter(this, [_d], void 0, function* ({ updates, oldRecord }) {
|
|
218
|
-
console.log('πͺ²edit.afterSave', JSON.stringify(updates, null, 2), '-----', JSON.stringify(oldRecord, null, 2));
|
|
219
218
|
if (oldRecord) {
|
|
220
219
|
// find lang which changed
|
|
221
220
|
let langsChanged = [];
|
|
@@ -223,10 +222,14 @@ export default class I18N extends AdminForthPlugin {
|
|
|
223
222
|
if (lang === 'en') {
|
|
224
223
|
continue;
|
|
225
224
|
}
|
|
225
|
+
if (updates[this.trFieldNames[lang]] !== undefined) {
|
|
226
|
+
langsChanged.push(lang);
|
|
227
|
+
}
|
|
226
228
|
}
|
|
227
229
|
// clear frontend cache for all langsChanged
|
|
228
230
|
for (const lang of langsChanged) {
|
|
229
|
-
this.cache.clear(`${this.resourceConfig.resourceId}
|
|
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]}`);
|
|
230
233
|
}
|
|
231
234
|
this.updateUntranslatedMenuBadge();
|
|
232
235
|
}
|
|
@@ -236,7 +239,8 @@ export default class I18N extends AdminForthPlugin {
|
|
|
236
239
|
// add hook on delete of any translation to reset cache
|
|
237
240
|
resourceConfig.hooks.delete.afterSave.push((_e) => __awaiter(this, [_e], void 0, function* ({ record }) {
|
|
238
241
|
for (const lang of this.options.supportedLanguages) {
|
|
239
|
-
|
|
242
|
+
// if frontend, clear frontend cache
|
|
243
|
+
this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}`);
|
|
240
244
|
this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
|
|
241
245
|
}
|
|
242
246
|
this.updateUntranslatedMenuBadge();
|
|
@@ -497,33 +501,13 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
497
501
|
return;
|
|
498
502
|
}
|
|
499
503
|
// loop over missingKeys[i].path and add them to database if not exists
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
yield
|
|
507
|
-
const key = missingKey.path;
|
|
508
|
-
const file = missingKey.file;
|
|
509
|
-
const category = 'frontend';
|
|
510
|
-
const exists = yield adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
|
|
511
|
-
if (exists) {
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
if (!key) {
|
|
515
|
-
throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
|
|
516
|
-
}
|
|
517
|
-
const record = Object.assign({ [this.enFieldName]: key, [this.options.categoryFieldName]: category }, (this.options.sourceFieldName ? { [this.options.sourceFieldName]: file } : {}));
|
|
518
|
-
try {
|
|
519
|
-
yield adminforth.resource(this.resourceConfig.resourceId).create(record);
|
|
520
|
-
}
|
|
521
|
-
catch (e) {
|
|
522
|
-
console.error('π Error creating record', e);
|
|
523
|
-
}
|
|
524
|
-
})));
|
|
525
|
-
// updateBadge
|
|
526
|
-
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');
|
|
527
511
|
});
|
|
528
512
|
}
|
|
529
513
|
tryProcessAndWatch(adminforth) {
|
|
@@ -641,6 +625,54 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
641
625
|
// Needed if plugin can have multiple instances on one resource
|
|
642
626
|
return `single`;
|
|
643
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
|
+
}
|
|
644
676
|
setupEndpoints(server) {
|
|
645
677
|
server.endpoint({
|
|
646
678
|
method: 'GET',
|
|
@@ -649,18 +681,7 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
649
681
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ query }) {
|
|
650
682
|
const lang = query.lang;
|
|
651
683
|
// form map of translations
|
|
652
|
-
const
|
|
653
|
-
const cacheKey = `${this.resourceConfig.resourceId}:frontend:${lang}`;
|
|
654
|
-
const cached = yield this.cache.get(cacheKey);
|
|
655
|
-
if (cached) {
|
|
656
|
-
return cached;
|
|
657
|
-
}
|
|
658
|
-
const translations = {};
|
|
659
|
-
const allTranslations = yield resource.list([Filters.EQ(this.options.categoryFieldName, 'frontend')]);
|
|
660
|
-
for (const tr of allTranslations) {
|
|
661
|
-
translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
|
|
662
|
-
}
|
|
663
|
-
yield this.cache.set(cacheKey, translations);
|
|
684
|
+
const translations = yield this.getCategoryTranslations('frontend', lang);
|
|
664
685
|
return translations;
|
|
665
686
|
})
|
|
666
687
|
});
|
package/index.ts
CHANGED
|
@@ -244,7 +244,6 @@ export default class I18N extends AdminForthPlugin {
|
|
|
244
244
|
|
|
245
245
|
// add hook on edit of any translation
|
|
246
246
|
resourceConfig.hooks.edit.afterSave.push(async ({ updates, oldRecord }: { updates: any, oldRecord?: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
247
|
-
console.log('πͺ²edit.afterSave', JSON.stringify(updates, null, 2),'-----', JSON.stringify(oldRecord, null, 2));
|
|
248
247
|
if (oldRecord) {
|
|
249
248
|
// find lang which changed
|
|
250
249
|
let langsChanged: LanguageCode[] = [];
|
|
@@ -252,26 +251,27 @@ export default class I18N extends AdminForthPlugin {
|
|
|
252
251
|
if (lang === 'en') {
|
|
253
252
|
continue;
|
|
254
253
|
}
|
|
254
|
+
if (updates[this.trFieldNames[lang]] !== undefined) {
|
|
255
|
+
langsChanged.push(lang);
|
|
256
|
+
}
|
|
255
257
|
}
|
|
256
|
-
|
|
258
|
+
|
|
257
259
|
// clear frontend cache for all langsChanged
|
|
258
260
|
for (const lang of langsChanged) {
|
|
259
|
-
this.cache.clear(`${this.resourceConfig.resourceId}
|
|
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]}`);
|
|
260
263
|
}
|
|
261
|
-
|
|
262
264
|
this.updateUntranslatedMenuBadge();
|
|
263
|
-
|
|
264
265
|
}
|
|
265
266
|
// clear frontend cache for all lan
|
|
266
|
-
|
|
267
|
-
|
|
268
267
|
return { ok: true };
|
|
269
268
|
});
|
|
270
269
|
|
|
271
270
|
// add hook on delete of any translation to reset cache
|
|
272
271
|
resourceConfig.hooks.delete.afterSave.push(async ({ record }: { record: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
273
272
|
for (const lang of this.options.supportedLanguages) {
|
|
274
|
-
|
|
273
|
+
// if frontend, clear frontend cache
|
|
274
|
+
this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}`);
|
|
275
275
|
this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
|
|
276
276
|
}
|
|
277
277
|
this.updateUntranslatedMenuBadge();
|
|
@@ -603,39 +603,16 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
603
603
|
return;
|
|
604
604
|
}
|
|
605
605
|
// loop over missingKeys[i].path and add them to database if not exists
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
}
|
|
611
|
-
return acc;
|
|
612
|
-
}, []);
|
|
613
|
-
|
|
614
|
-
await Promise.all(missingKeysDeduplicated.map(async (missingKey: any) => {
|
|
615
|
-
const key = missingKey.path;
|
|
616
|
-
const file = missingKey.file;
|
|
617
|
-
const category = 'frontend';
|
|
618
|
-
const exists = await adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
|
|
619
|
-
if (exists) {
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
if (!key) {
|
|
623
|
-
throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
|
|
624
|
-
}
|
|
625
|
-
const record = {
|
|
626
|
-
[this.enFieldName]: key,
|
|
627
|
-
[this.options.categoryFieldName]: category,
|
|
628
|
-
...(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,
|
|
629
610
|
};
|
|
630
|
-
|
|
631
|
-
await adminforth.resource(this.resourceConfig.resourceId).create(record);
|
|
632
|
-
} catch (e) {
|
|
633
|
-
console.error('π Error creating record', e);
|
|
634
|
-
}
|
|
635
|
-
}));
|
|
611
|
+
});
|
|
636
612
|
|
|
637
|
-
|
|
638
|
-
|
|
613
|
+
await this.feedCategoryTranslations(messagesForFeed, 'frontend')
|
|
614
|
+
|
|
615
|
+
|
|
639
616
|
}
|
|
640
617
|
|
|
641
618
|
|
|
@@ -764,6 +741,60 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
764
741
|
return `single`;
|
|
765
742
|
}
|
|
766
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
|
+
|
|
767
798
|
|
|
768
799
|
setupEndpoints(server: IHttpServer) {
|
|
769
800
|
server.endpoint({
|
|
@@ -774,18 +805,7 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
774
805
|
const lang = query.lang;
|
|
775
806
|
|
|
776
807
|
// form map of translations
|
|
777
|
-
const
|
|
778
|
-
const cacheKey = `${this.resourceConfig.resourceId}:frontend:${lang}`;
|
|
779
|
-
const cached = await this.cache.get(cacheKey);
|
|
780
|
-
if (cached) {
|
|
781
|
-
return cached;
|
|
782
|
-
}
|
|
783
|
-
const translations = {};
|
|
784
|
-
const allTranslations = await resource.list([Filters.EQ(this.options.categoryFieldName, 'frontend')]);
|
|
785
|
-
for (const tr of allTranslations) {
|
|
786
|
-
translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
|
|
787
|
-
}
|
|
788
|
-
await this.cache.set(cacheKey, translations);
|
|
808
|
+
const translations = await this.getCategoryTranslations('frontend', lang);
|
|
789
809
|
return translations;
|
|
790
810
|
|
|
791
811
|
}
|