@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 +7 -1
- package/dist/index.js +61 -52
- package/index.ts +68 -54
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
232
|
-
|
|
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
|
-
|
|
248
|
-
|
|
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
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
yield
|
|
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
|
|
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
|
-
|
|
262
|
-
|
|
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
|
-
|
|
278
|
-
|
|
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
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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
|
-
|
|
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
|
-
|
|
644
|
-
|
|
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
|
|
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
|
}
|