@adminforth/i18n 1.0.23-next.0 → 1.0.23-next.1
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 +9 -0
- package/custom/LanguageUnderLogin.vue +5 -2
- package/dist/custom/LanguageUnderLogin.vue +5 -2
- package/dist/index.js +35 -3
- package/index.ts +42 -3
- package/package.json +1 -1
package/Changelog.md
CHANGED
|
@@ -5,6 +5,15 @@ 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.23] - next
|
|
9
|
+
|
|
10
|
+
### Improved
|
|
11
|
+
|
|
12
|
+
- Better instructions for LLM pluralization Slavik messages
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- support for pluralization in Backend `tr` function
|
|
16
|
+
|
|
8
17
|
## [1.0.22]
|
|
9
18
|
|
|
10
19
|
### Fixed
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
import Select from '@/afcl/Select.vue';
|
|
33
33
|
import 'flag-icon-css/css/flag-icons.min.css';
|
|
34
34
|
import { setLang, getCountryCodeFromLangCode, getLocalLang } from './langCommon';
|
|
35
|
+
import { useCoreStore } from '@/stores/core';
|
|
35
36
|
|
|
36
37
|
import { computed, ref, onMounted, watch } from 'vue';
|
|
37
38
|
import { useI18n } from 'vue-i18n';
|
|
@@ -42,9 +43,11 @@ const { setLocaleMessage, locale } = useI18n();
|
|
|
42
43
|
const props = defineProps(['meta', 'resource']);
|
|
43
44
|
|
|
44
45
|
const selectedLanguage = ref('');
|
|
46
|
+
const coreStore = useCoreStore();
|
|
45
47
|
|
|
46
|
-
watch(() => selectedLanguage.value, (newVal) => {
|
|
47
|
-
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
48
|
+
watch(() => selectedLanguage.value, async (newVal) => {
|
|
49
|
+
await setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
50
|
+
coreStore.getPublicConfig();
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
import Select from '@/afcl/Select.vue';
|
|
33
33
|
import 'flag-icon-css/css/flag-icons.min.css';
|
|
34
34
|
import { setLang, getCountryCodeFromLangCode, getLocalLang } from './langCommon';
|
|
35
|
+
import { useCoreStore } from '@/stores/core';
|
|
35
36
|
|
|
36
37
|
import { computed, ref, onMounted, watch } from 'vue';
|
|
37
38
|
import { useI18n } from 'vue-i18n';
|
|
@@ -42,9 +43,11 @@ const { setLocaleMessage, locale } = useI18n();
|
|
|
42
43
|
const props = defineProps(['meta', 'resource']);
|
|
43
44
|
|
|
44
45
|
const selectedLanguage = ref('');
|
|
46
|
+
const coreStore = useCoreStore();
|
|
45
47
|
|
|
46
|
-
watch(() => selectedLanguage.value, (newVal) => {
|
|
47
|
-
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
48
|
+
watch(() => selectedLanguage.value, async (newVal) => {
|
|
49
|
+
await setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
50
|
+
coreStore.getPublicConfig();
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
|
package/dist/index.js
CHANGED
|
@@ -380,7 +380,7 @@ export default class I18nPlugin extends AdminForthPlugin {
|
|
|
380
380
|
const requestSlavicPlurals = Object.keys(SLAVIC_PLURAL_EXAMPLES).includes(lang) && plurals;
|
|
381
381
|
const prompt = `
|
|
382
382
|
I need to translate strings in JSON to ${lang} (${langName}) language from English for my web app.
|
|
383
|
-
${requestSlavicPlurals ? `You should provide 4
|
|
383
|
+
${requestSlavicPlurals ? `You should provide 4 slavic forms (in format "zero count | singular count | 2-4 | 5+") e.g. "apple | apples" should become "${SLAVIC_PLURAL_EXAMPLES[lang]}"` : ''}
|
|
384
384
|
Keep keys, as is, write translation into values! Here are the strings:
|
|
385
385
|
|
|
386
386
|
\`\`\`json
|
|
@@ -474,8 +474,10 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
474
474
|
totalTranslated = totalTranslated.concat(noPluralKeys, pluralKeys);
|
|
475
475
|
})));
|
|
476
476
|
yield Promise.all(Object.entries(updateStrings).map((_c) => __awaiter(this, [_c], void 0, function* ([_, { updates, strId }]) {
|
|
477
|
+
// get old full record
|
|
478
|
+
const oldRecord = yield this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ(this.primaryKeyFieldName, strId)]);
|
|
477
479
|
// because this will translate all languages, we can set completedLangs to all languages
|
|
478
|
-
const futureCompletedFieldValue = yield this.computeCompletedFieldValue(updates);
|
|
480
|
+
const futureCompletedFieldValue = yield this.computeCompletedFieldValue(Object.assign(Object.assign({}, oldRecord), updates));
|
|
479
481
|
yield this.adminforth.resource(this.resourceConfig.resourceId).update(strId, Object.assign(Object.assign({}, updates), { [this.options.completedFieldName]: futureCompletedFieldValue }));
|
|
480
482
|
})));
|
|
481
483
|
for (const lang of langsInvolved) {
|
|
@@ -565,7 +567,7 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
565
567
|
}
|
|
566
568
|
// in this plugin we will use plugin to fill the database with missing language messages
|
|
567
569
|
this.tryProcessAndWatch(adminforth);
|
|
568
|
-
adminforth.tr = (msg, category, lang, params) => __awaiter(this, void 0, void 0, function* () {
|
|
570
|
+
adminforth.tr = (msg, category, lang, params, pluralizationNumber) => __awaiter(this, void 0, void 0, function* () {
|
|
569
571
|
if (!msg) {
|
|
570
572
|
return msg;
|
|
571
573
|
}
|
|
@@ -612,6 +614,10 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
612
614
|
// cache so even if key does not exist, we will not hit database
|
|
613
615
|
yield this.cache.set(cacheKey, result);
|
|
614
616
|
}
|
|
617
|
+
// if msg has '|' in it, then we need to aplly pluralization
|
|
618
|
+
if (msg.includes('|')) {
|
|
619
|
+
result = this.applyPluralization(result, pluralizationNumber, lang);
|
|
620
|
+
}
|
|
615
621
|
if (params) {
|
|
616
622
|
for (const [key, value] of Object.entries(params)) {
|
|
617
623
|
result = result.replace(`{${key}}`, value);
|
|
@@ -620,6 +626,32 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
620
626
|
return result;
|
|
621
627
|
});
|
|
622
628
|
}
|
|
629
|
+
applyPluralization(str, number, lang) {
|
|
630
|
+
const choices = str.split('|');
|
|
631
|
+
const choicesLength = choices.length;
|
|
632
|
+
if (choicesLength > 2) {
|
|
633
|
+
// this is slavic pluralization
|
|
634
|
+
return choices[this.slavicPluralRule(number, choicesLength)];
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
return number === 1 ? choices[0] : choices[1];
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
// taken from here https://vue-i18n.intlify.dev/guide/essentials/pluralization.html#custom-pluralization
|
|
641
|
+
slavicPluralRule(choice, choicesLength) {
|
|
642
|
+
if (choice === 0) {
|
|
643
|
+
return 0;
|
|
644
|
+
}
|
|
645
|
+
const teen = choice > 10 && choice < 20;
|
|
646
|
+
const endsWithOne = choice % 10 === 1;
|
|
647
|
+
if (!teen && endsWithOne) {
|
|
648
|
+
return 1;
|
|
649
|
+
}
|
|
650
|
+
if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
|
|
651
|
+
return 2;
|
|
652
|
+
}
|
|
653
|
+
return choicesLength < 4 ? 2 : 3;
|
|
654
|
+
}
|
|
623
655
|
instanceUniqueRepresentation(pluginOptions) {
|
|
624
656
|
// optional method to return unique string representation of plugin instance.
|
|
625
657
|
// Needed if plugin can have multiple instances on one resource
|
package/index.ts
CHANGED
|
@@ -429,7 +429,7 @@ export default class I18nPlugin extends AdminForthPlugin {
|
|
|
429
429
|
|
|
430
430
|
const prompt = `
|
|
431
431
|
I need to translate strings in JSON to ${lang} (${langName}) language from English for my web app.
|
|
432
|
-
${requestSlavicPlurals ? `You should provide 4
|
|
432
|
+
${requestSlavicPlurals ? `You should provide 4 slavic forms (in format "zero count | singular count | 2-4 | 5+") e.g. "apple | apples" should become "${SLAVIC_PLURAL_EXAMPLES[lang]}"` : ''}
|
|
433
433
|
Keep keys, as is, write translation into values! Here are the strings:
|
|
434
434
|
|
|
435
435
|
\`\`\`json
|
|
@@ -449,6 +449,7 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
449
449
|
300,
|
|
450
450
|
);
|
|
451
451
|
|
|
452
|
+
|
|
452
453
|
if (resp.error) {
|
|
453
454
|
throw new AiTranslateError(resp.error);
|
|
454
455
|
}
|
|
@@ -568,8 +569,11 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
568
569
|
await Promise.all(
|
|
569
570
|
Object.entries(updateStrings).map(
|
|
570
571
|
async ([_, { updates, strId }]: [string, { updates: any, category: string, strId: string }]) => {
|
|
572
|
+
// get old full record
|
|
573
|
+
const oldRecord = await this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ(this.primaryKeyFieldName, strId)]);
|
|
574
|
+
|
|
571
575
|
// because this will translate all languages, we can set completedLangs to all languages
|
|
572
|
-
const futureCompletedFieldValue = await this.computeCompletedFieldValue(updates);
|
|
576
|
+
const futureCompletedFieldValue = await this.computeCompletedFieldValue({ ...oldRecord, ...updates });
|
|
573
577
|
|
|
574
578
|
await this.adminforth.resource(this.resourceConfig.resourceId).update(strId, {
|
|
575
579
|
...updates,
|
|
@@ -675,7 +679,7 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
675
679
|
// in this plugin we will use plugin to fill the database with missing language messages
|
|
676
680
|
this.tryProcessAndWatch(adminforth);
|
|
677
681
|
|
|
678
|
-
adminforth.tr = async (msg: string | null | undefined, category: string, lang: string, params): Promise<string> => {
|
|
682
|
+
adminforth.tr = async (msg: string | null | undefined, category: string, lang: string, params, pluralizationNumber: number): Promise<string> => {
|
|
679
683
|
if (!msg) {
|
|
680
684
|
return msg;
|
|
681
685
|
}
|
|
@@ -726,6 +730,11 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
726
730
|
// cache so even if key does not exist, we will not hit database
|
|
727
731
|
await this.cache.set(cacheKey, result);
|
|
728
732
|
}
|
|
733
|
+
// if msg has '|' in it, then we need to aplly pluralization
|
|
734
|
+
if (msg.includes('|')) {
|
|
735
|
+
result = this.applyPluralization(result, pluralizationNumber, lang);
|
|
736
|
+
}
|
|
737
|
+
|
|
729
738
|
if (params) {
|
|
730
739
|
for (const [key, value] of Object.entries(params)) {
|
|
731
740
|
result = result.replace(`{${key}}`, value);
|
|
@@ -735,6 +744,36 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
|
|
|
735
744
|
}
|
|
736
745
|
}
|
|
737
746
|
|
|
747
|
+
applyPluralization(str: string, number: number, lang: string): string {
|
|
748
|
+
const choices = str.split('|');
|
|
749
|
+
const choicesLength = choices.length;
|
|
750
|
+
|
|
751
|
+
if (choicesLength > 2) {
|
|
752
|
+
// this is slavic pluralization
|
|
753
|
+
return choices[this.slavicPluralRule(number, choicesLength)];
|
|
754
|
+
} else {
|
|
755
|
+
return number === 1 ? choices[0] : choices[1];
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// taken from here https://vue-i18n.intlify.dev/guide/essentials/pluralization.html#custom-pluralization
|
|
760
|
+
slavicPluralRule(choice, choicesLength) {
|
|
761
|
+
if (choice === 0) {
|
|
762
|
+
return 0
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const teen = choice > 10 && choice < 20
|
|
766
|
+
const endsWithOne = choice % 10 === 1
|
|
767
|
+
|
|
768
|
+
if (!teen && endsWithOne) {
|
|
769
|
+
return 1
|
|
770
|
+
}
|
|
771
|
+
if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
|
|
772
|
+
return 2
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
return choicesLength < 4 ? 2 : 3
|
|
776
|
+
}
|
|
738
777
|
instanceUniqueRepresentation(pluginOptions: any) : string {
|
|
739
778
|
// optional method to return unique string representation of plugin instance.
|
|
740
779
|
// Needed if plugin can have multiple instances on one resource
|