@adminforth/i18n 1.0.4 → 1.0.6
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/custom/LanguageInUserMenu.vue +53 -30
- package/dist/custom/LanguageInUserMenu.vue +53 -30
- package/dist/index.js +29 -1
- package/index.ts +34 -2
- package/package.json +1 -1
|
@@ -1,35 +1,48 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
:
|
|
2
|
+
<div>
|
|
3
|
+
<div class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black
|
|
4
|
+
hover:bg-html dark:text-darkSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextActive
|
|
5
|
+
w-full select-none "
|
|
6
|
+
:class="{ 'bg-black bg-opacity-10 ': showDropdown }"
|
|
7
|
+
@click="showDropdown = !showDropdown"
|
|
7
8
|
>
|
|
8
|
-
<
|
|
9
|
-
<span class="
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
9
|
+
<span class="mr-1">
|
|
10
|
+
<span class="flag-icon"
|
|
11
|
+
:class="`flag-icon-${getCountryCodeFromLangCode(selectedOption.value)}`"
|
|
12
|
+
></span>
|
|
13
|
+
</span>
|
|
14
|
+
<span>{{ selectedOption.label }}</span>
|
|
15
|
+
|
|
16
|
+
<IconCaretDownSolid class="h-5 w-5 text-lightPrimary dark:text-gray-400 opacity-50 transition duration-150 ease-in"
|
|
17
|
+
:class="{ 'transform rotate-180': showDropdown }"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div v-if="showDropdown" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm
|
|
22
|
+
text-black dark:text-darkSidebarTextHover
|
|
23
|
+
bg-black bg-opacity-10
|
|
24
|
+
hover:bg-html dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextActive
|
|
25
|
+
w-full text-select-none pl-5 select-none"
|
|
26
|
+
v-for="option in options.filter((opt) => opt.value !== selectedOption.value)"
|
|
27
|
+
@click="doChangeLang(option.value)"
|
|
28
|
+
>
|
|
29
|
+
<span class="mr-1">
|
|
30
|
+
<span class="flag-icon"
|
|
31
|
+
:class="`flag-icon-${getCountryCodeFromLangCode(option.value)}`"
|
|
32
|
+
></span>
|
|
33
|
+
</span>
|
|
34
|
+
<span>{{ option.label }}</span>
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
</div>
|
|
28
40
|
</template>
|
|
29
41
|
|
|
30
42
|
<script setup>
|
|
31
|
-
import Select from '@/afcl/Select.vue';
|
|
32
43
|
import 'flag-icon-css/css/flag-icons.min.css';
|
|
44
|
+
import { IconCaretDownSolid } from '@iconify-prerendered/vue-flowbite';
|
|
45
|
+
|
|
33
46
|
import { setLang, getCountryCodeFromLangCode, getLocalLang } from './langCommon';
|
|
34
47
|
|
|
35
48
|
import { computed, ref, onMounted, watch } from 'vue';
|
|
@@ -37,15 +50,17 @@ import { useI18n } from 'vue-i18n';
|
|
|
37
50
|
|
|
38
51
|
const { setLocaleMessage, locale } = useI18n();
|
|
39
52
|
|
|
40
|
-
|
|
53
|
+
const showDropdown = ref(false);
|
|
41
54
|
const props = defineProps(['meta', 'resource']);
|
|
42
55
|
|
|
43
56
|
const selectedLanguage = ref('');
|
|
44
57
|
|
|
58
|
+
function doChangeLang(lang) {
|
|
59
|
+
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, lang);
|
|
60
|
+
// unfortunately, we need this to recall all APIs
|
|
61
|
+
document.location.reload();
|
|
45
62
|
|
|
46
|
-
|
|
47
|
-
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
48
|
-
});
|
|
63
|
+
}
|
|
49
64
|
|
|
50
65
|
|
|
51
66
|
const options = computed(() => {
|
|
@@ -57,6 +72,14 @@ const options = computed(() => {
|
|
|
57
72
|
});
|
|
58
73
|
});
|
|
59
74
|
|
|
75
|
+
const selectedOption = computed(() => {
|
|
76
|
+
const val = options.value.find((option) => option.value === selectedLanguage.value);
|
|
77
|
+
if (val) {
|
|
78
|
+
return val;
|
|
79
|
+
}
|
|
80
|
+
return options.value[0];
|
|
81
|
+
});
|
|
82
|
+
|
|
60
83
|
|
|
61
84
|
onMounted(() => {
|
|
62
85
|
console.log('Language In user menu mounted', props.meta.supportedLanguages);
|
|
@@ -1,35 +1,48 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
:
|
|
2
|
+
<div>
|
|
3
|
+
<div class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black
|
|
4
|
+
hover:bg-html dark:text-darkSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextActive
|
|
5
|
+
w-full select-none "
|
|
6
|
+
:class="{ 'bg-black bg-opacity-10 ': showDropdown }"
|
|
7
|
+
@click="showDropdown = !showDropdown"
|
|
7
8
|
>
|
|
8
|
-
<
|
|
9
|
-
<span class="
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
9
|
+
<span class="mr-1">
|
|
10
|
+
<span class="flag-icon"
|
|
11
|
+
:class="`flag-icon-${getCountryCodeFromLangCode(selectedOption.value)}`"
|
|
12
|
+
></span>
|
|
13
|
+
</span>
|
|
14
|
+
<span>{{ selectedOption.label }}</span>
|
|
15
|
+
|
|
16
|
+
<IconCaretDownSolid class="h-5 w-5 text-lightPrimary dark:text-gray-400 opacity-50 transition duration-150 ease-in"
|
|
17
|
+
:class="{ 'transform rotate-180': showDropdown }"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div v-if="showDropdown" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm
|
|
22
|
+
text-black dark:text-darkSidebarTextHover
|
|
23
|
+
bg-black bg-opacity-10
|
|
24
|
+
hover:bg-html dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextActive
|
|
25
|
+
w-full text-select-none pl-5 select-none"
|
|
26
|
+
v-for="option in options.filter((opt) => opt.value !== selectedOption.value)"
|
|
27
|
+
@click="doChangeLang(option.value)"
|
|
28
|
+
>
|
|
29
|
+
<span class="mr-1">
|
|
30
|
+
<span class="flag-icon"
|
|
31
|
+
:class="`flag-icon-${getCountryCodeFromLangCode(option.value)}`"
|
|
32
|
+
></span>
|
|
33
|
+
</span>
|
|
34
|
+
<span>{{ option.label }}</span>
|
|
35
|
+
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
</div>
|
|
28
40
|
</template>
|
|
29
41
|
|
|
30
42
|
<script setup>
|
|
31
|
-
import Select from '@/afcl/Select.vue';
|
|
32
43
|
import 'flag-icon-css/css/flag-icons.min.css';
|
|
44
|
+
import { IconCaretDownSolid } from '@iconify-prerendered/vue-flowbite';
|
|
45
|
+
|
|
33
46
|
import { setLang, getCountryCodeFromLangCode, getLocalLang } from './langCommon';
|
|
34
47
|
|
|
35
48
|
import { computed, ref, onMounted, watch } from 'vue';
|
|
@@ -37,15 +50,17 @@ import { useI18n } from 'vue-i18n';
|
|
|
37
50
|
|
|
38
51
|
const { setLocaleMessage, locale } = useI18n();
|
|
39
52
|
|
|
40
|
-
|
|
53
|
+
const showDropdown = ref(false);
|
|
41
54
|
const props = defineProps(['meta', 'resource']);
|
|
42
55
|
|
|
43
56
|
const selectedLanguage = ref('');
|
|
44
57
|
|
|
58
|
+
function doChangeLang(lang) {
|
|
59
|
+
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, lang);
|
|
60
|
+
// unfortunately, we need this to recall all APIs
|
|
61
|
+
document.location.reload();
|
|
45
62
|
|
|
46
|
-
|
|
47
|
-
setLang({ setLocaleMessage, locale }, props.meta.pluginInstanceId, newVal);
|
|
48
|
-
});
|
|
63
|
+
}
|
|
49
64
|
|
|
50
65
|
|
|
51
66
|
const options = computed(() => {
|
|
@@ -57,6 +72,14 @@ const options = computed(() => {
|
|
|
57
72
|
});
|
|
58
73
|
});
|
|
59
74
|
|
|
75
|
+
const selectedOption = computed(() => {
|
|
76
|
+
const val = options.value.find((option) => option.value === selectedLanguage.value);
|
|
77
|
+
if (val) {
|
|
78
|
+
return val;
|
|
79
|
+
}
|
|
80
|
+
return options.value[0];
|
|
81
|
+
});
|
|
82
|
+
|
|
60
83
|
|
|
61
84
|
onMounted(() => {
|
|
62
85
|
console.log('Language In user menu mounted', props.meta.supportedLanguages);
|
package/dist/index.js
CHANGED
|
@@ -131,7 +131,7 @@ export default class I18N extends AdminForthPlugin {
|
|
|
131
131
|
// if showIn is not defined, add it as empty
|
|
132
132
|
column.showIn = [];
|
|
133
133
|
// add virtual field for incomplete
|
|
134
|
-
resourceConfig.columns.
|
|
134
|
+
resourceConfig.columns.unshift({
|
|
135
135
|
name: 'fully_translated',
|
|
136
136
|
label: 'Fully translated',
|
|
137
137
|
virtual: true,
|
|
@@ -257,6 +257,28 @@ export default class I18N extends AdminForthPlugin {
|
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
259
|
;
|
|
260
|
+
// if there is menu item with resourceId, add .badge function showing number of untranslated strings
|
|
261
|
+
const addBadgeCountToMenuItem = (menuItem) => {
|
|
262
|
+
console.log('🪲menuItem, registring ', menuItem);
|
|
263
|
+
menuItem.badge = () => __awaiter(this, void 0, void 0, function* () {
|
|
264
|
+
const resource = adminforth.resource(menuItem.resourceId);
|
|
265
|
+
const count = yield resource.count([Filters.NEQ(this.options.completedFieldName, this.fullCompleatedFieldValue)]);
|
|
266
|
+
return `${count}`;
|
|
267
|
+
});
|
|
268
|
+
menuItem.badgeTooltip = 'Untranslated count';
|
|
269
|
+
};
|
|
270
|
+
adminforth.config.menu.forEach((menuItem) => {
|
|
271
|
+
if (menuItem.resourceId === resourceConfig.resourceId) {
|
|
272
|
+
addBadgeCountToMenuItem(menuItem);
|
|
273
|
+
}
|
|
274
|
+
if (menuItem.children) {
|
|
275
|
+
menuItem.children.forEach((child) => {
|
|
276
|
+
if (child.resourceId === resourceConfig.resourceId) {
|
|
277
|
+
addBadgeCountToMenuItem(child);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
});
|
|
260
282
|
});
|
|
261
283
|
}
|
|
262
284
|
bulkTranslate(_a) {
|
|
@@ -376,6 +398,9 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
376
398
|
if (exists) {
|
|
377
399
|
return;
|
|
378
400
|
}
|
|
401
|
+
if (!key) {
|
|
402
|
+
throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
|
|
403
|
+
}
|
|
379
404
|
const record = Object.assign({ [this.enFieldName]: key, [this.options.categoryFieldName]: category }, (this.options.sourceFieldName ? { [this.options.sourceFieldName]: file } : {}));
|
|
380
405
|
try {
|
|
381
406
|
yield adminforth.resource(this.resourceConfig.resourceId).create(record);
|
|
@@ -450,6 +475,9 @@ ${JSON.stringify(strings.reduce((acc, s) => {
|
|
|
450
475
|
const resource = adminforth.resource(resourceConfig.resourceId);
|
|
451
476
|
const translation = yield resource.get([Filters.EQ(this.enFieldName, msg), Filters.EQ(this.options.categoryFieldName, category)]);
|
|
452
477
|
if (!translation) {
|
|
478
|
+
if (!msg) {
|
|
479
|
+
throw Error(`Empty string passed to tr function during translation`);
|
|
480
|
+
}
|
|
453
481
|
yield resource.create({
|
|
454
482
|
[this.enFieldName]: msg,
|
|
455
483
|
[this.options.categoryFieldName]: category,
|
package/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AdminForth, { AdminForthPlugin, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
|
|
2
|
-
import type { IAdminForth, IHttpServer, AdminForthComponentDeclaration, AdminForthResourceColumn, AdminForthResource, BeforeLoginConfirmationFunction } from "adminforth";
|
|
2
|
+
import type { IAdminForth, IHttpServer, AdminForthComponentDeclaration, AdminForthResourceColumn, AdminForthResource, BeforeLoginConfirmationFunction, AdminForthConfigMenuItem } from "adminforth";
|
|
3
3
|
import type { PluginOptions } from './types.js';
|
|
4
4
|
import iso6391, { LanguageCode } from 'iso-639-1';
|
|
5
5
|
import path from 'path';
|
|
@@ -147,7 +147,7 @@ export default class I18N extends AdminForthPlugin {
|
|
|
147
147
|
column.showIn = [];
|
|
148
148
|
|
|
149
149
|
// add virtual field for incomplete
|
|
150
|
-
resourceConfig.columns.
|
|
150
|
+
resourceConfig.columns.unshift({
|
|
151
151
|
name: 'fully_translated',
|
|
152
152
|
label: 'Fully translated',
|
|
153
153
|
virtual: true,
|
|
@@ -294,6 +294,31 @@ export default class I18N extends AdminForthPlugin {
|
|
|
294
294
|
}
|
|
295
295
|
);
|
|
296
296
|
};
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
// if there is menu item with resourceId, add .badge function showing number of untranslated strings
|
|
300
|
+
|
|
301
|
+
const addBadgeCountToMenuItem = (menuItem: AdminForthConfigMenuItem) => {
|
|
302
|
+
console.log('🪲menuItem, registring ', menuItem);
|
|
303
|
+
menuItem.badge = async () => {
|
|
304
|
+
const resource = adminforth.resource(menuItem.resourceId);
|
|
305
|
+
const count = await resource.count([Filters.NEQ(this.options.completedFieldName, this.fullCompleatedFieldValue)]);
|
|
306
|
+
return `${count}`;
|
|
307
|
+
};
|
|
308
|
+
menuItem.badgeTooltip = 'Untranslated count';
|
|
309
|
+
}
|
|
310
|
+
adminforth.config.menu.forEach((menuItem) => {
|
|
311
|
+
if (menuItem.resourceId === resourceConfig.resourceId) {
|
|
312
|
+
addBadgeCountToMenuItem(menuItem);
|
|
313
|
+
}
|
|
314
|
+
if (menuItem.children) {
|
|
315
|
+
menuItem.children.forEach((child) => {
|
|
316
|
+
if (child.resourceId === resourceConfig.resourceId) {
|
|
317
|
+
addBadgeCountToMenuItem(child);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
});
|
|
297
322
|
}
|
|
298
323
|
|
|
299
324
|
async bulkTranslate({ selectedIds }: { selectedIds: string[] }) {
|
|
@@ -450,6 +475,9 @@ ${
|
|
|
450
475
|
if (exists) {
|
|
451
476
|
return;
|
|
452
477
|
}
|
|
478
|
+
if (!key) {
|
|
479
|
+
throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
|
|
480
|
+
}
|
|
453
481
|
const record = {
|
|
454
482
|
[this.enFieldName]: key,
|
|
455
483
|
[this.options.categoryFieldName]: category,
|
|
@@ -535,6 +563,10 @@ ${
|
|
|
535
563
|
const resource = adminforth.resource(resourceConfig.resourceId);
|
|
536
564
|
const translation = await resource.get([Filters.EQ(this.enFieldName, msg), Filters.EQ(this.options.categoryFieldName, category)]);
|
|
537
565
|
if (!translation) {
|
|
566
|
+
|
|
567
|
+
if (!msg) {
|
|
568
|
+
throw Error(`Empty string passed to tr function during translation`);
|
|
569
|
+
}
|
|
538
570
|
await resource.create({
|
|
539
571
|
[this.enFieldName]: msg,
|
|
540
572
|
[this.options.categoryFieldName]: category,
|