@flusys/ng-localization 4.1.1 → 5.0.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/README.md +71 -387
- package/fesm2022/flusys-ng-localization.mjs +576 -922
- package/fesm2022/flusys-ng-localization.mjs.map +1 -1
- package/package.json +3 -3
- package/types/flusys-ng-localization.d.ts +12 -86
|
@@ -5,31 +5,30 @@ import { PrimeNG } from 'primeng/config';
|
|
|
5
5
|
import { HttpClient } from '@angular/common/http';
|
|
6
6
|
import { APP_CONFIG, TRANSLATE_ADAPTER } from '@flusys/ng-core';
|
|
7
7
|
import { firstValueFrom, from, fromEvent, finalize, forkJoin } from 'rxjs';
|
|
8
|
+
import { ApiResourceService, resolveTranslationModule, SHARED_MESSAGES, PermissionValidatorService, LANGUAGE_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TranslatePipe, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
|
|
8
9
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
9
10
|
import * as i1 from 'primeng/styleclass';
|
|
10
11
|
import { StyleClassModule } from 'primeng/styleclass';
|
|
11
12
|
import { filter } from 'rxjs/operators';
|
|
12
13
|
import { LAYOUT_LANGUAGE_SELECTOR, LAYOUT_LANGUAGE_SELECTOR_PANEL } from '@flusys/ng-layout';
|
|
13
|
-
import { resolveTranslationModule, SHARED_MESSAGES, PermissionValidatorService, LANGUAGE_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TRANSLATION_PERMISSIONS, TranslatePipe, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
|
|
14
14
|
import { RouterOutlet, RouterLink, RouterLinkActive, Router, ActivatedRoute } from '@angular/router';
|
|
15
15
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
|
16
16
|
import * as i2 from 'primeng/button';
|
|
17
17
|
import * as i2$1 from 'primeng/confirmdialog';
|
|
18
|
-
import * as
|
|
18
|
+
import * as i3 from 'primeng/table';
|
|
19
19
|
import * as i4 from 'primeng/tag';
|
|
20
|
-
import * as
|
|
20
|
+
import * as i5 from 'primeng/toast';
|
|
21
21
|
import * as i6 from 'primeng/tooltip';
|
|
22
22
|
import * as i1$1 from '@angular/forms';
|
|
23
23
|
import { FormsModule } from '@angular/forms';
|
|
24
24
|
import { form, required, maxLength, FormField } from '@angular/forms/signals';
|
|
25
|
-
import * as i3 from 'primeng/card';
|
|
25
|
+
import * as i3$1 from 'primeng/card';
|
|
26
26
|
import * as i4$1 from 'primeng/inputtext';
|
|
27
|
-
import * as i5 from 'primeng/select';
|
|
27
|
+
import * as i5$1 from 'primeng/select';
|
|
28
28
|
import * as i4$2 from 'primeng/iconfield';
|
|
29
|
-
import * as i5$
|
|
29
|
+
import * as i5$2 from 'primeng/inputicon';
|
|
30
30
|
import * as i7 from 'primeng/textarea';
|
|
31
31
|
import * as i9 from 'primeng/progressspinner';
|
|
32
|
-
import * as i3$1 from 'primeng/checkbox';
|
|
33
32
|
|
|
34
33
|
const LOCALIZATION_CONFIG = new InjectionToken('LOCALIZATION_CONFIG');
|
|
35
34
|
/** Get localization config with sensible defaults applied */
|
|
@@ -52,106 +51,17 @@ const STORAGE_KEYS = {
|
|
|
52
51
|
};
|
|
53
52
|
|
|
54
53
|
const LOCALIZATION_MESSAGES = {
|
|
55
|
-
// Container
|
|
56
|
-
'localization.title': 'Localization',
|
|
57
|
-
'localization.subtitle': 'Manage languages and translations',
|
|
58
|
-
// Tabs
|
|
59
|
-
'localization.tabs.languages': 'Languages',
|
|
60
|
-
'localization.tabs.keys': 'Keys',
|
|
61
|
-
'localization.tabs.translations': 'Translations',
|
|
62
|
-
// Languages
|
|
63
|
-
'localization.language.title': 'Languages',
|
|
64
|
-
'localization.language.subtitle': 'Manage available languages for your application',
|
|
65
|
-
'localization.language.create': 'Add Language',
|
|
66
|
-
'localization.language.edit': 'Edit Language',
|
|
67
|
-
'localization.language.code': 'Language Code',
|
|
68
|
-
'localization.language.name': 'Language Name',
|
|
69
|
-
'localization.language.native.name': 'Native Name',
|
|
70
|
-
'localization.language.direction': 'Text Direction',
|
|
71
|
-
'localization.language.ltr': 'LTR',
|
|
72
|
-
'localization.language.rtl': 'RTL',
|
|
73
|
-
'localization.language.active': 'Active',
|
|
74
|
-
'localization.language.default': 'Default',
|
|
75
|
-
'localization.language.set.default': 'Set as Default',
|
|
76
|
-
'localization.language.confirm.set.default': 'Set "{{name}}" as the default language?',
|
|
77
|
-
'localization.language.set.default.success': '{{name}} is now the default language.',
|
|
78
|
-
'localization.language.delete.title': 'Delete Language',
|
|
79
|
-
'localization.language.empty': 'No languages configured. Add a language to get started.',
|
|
80
|
-
'localization.language.display.order': 'Display Order',
|
|
81
|
-
'localization.language.iso.code.hint': 'ISO 639-1 language code (e.g., en, ar, fr)',
|
|
82
|
-
'localization.language.native.name.hint': 'Name in the native language (e.g., العربية for Arabic)',
|
|
83
|
-
'localization.language.create.success': 'Language created successfully',
|
|
84
|
-
'localization.language.update.success': 'Language updated successfully',
|
|
85
|
-
// Translation keys
|
|
86
|
-
'localization.key.title': 'Translation Keys',
|
|
87
|
-
'localization.key.subtitle': 'Manage translation keys for your application',
|
|
88
|
-
'localization.key.create': 'Add Key',
|
|
89
|
-
'localization.key.edit': 'Edit Key',
|
|
90
|
-
'localization.key.key': 'Key',
|
|
91
|
-
'localization.key.name': 'Key Name',
|
|
92
|
-
'localization.key.module': 'Module',
|
|
93
|
-
'localization.key.default.message': 'Default Message',
|
|
94
|
-
'localization.key.description': 'Description',
|
|
95
|
-
'localization.key.variables': 'Variables',
|
|
96
|
-
'localization.key.variables.hint': 'Enter variable names used in this translation',
|
|
97
|
-
'localization.key.variables.placeholder': 'e.g., name, count, date',
|
|
98
|
-
'localization.key.translations': 'Translations',
|
|
99
|
-
'localization.key.translations.section': 'Translations',
|
|
100
|
-
'localization.key.about': 'Key Information',
|
|
101
|
-
'localization.key.filter.module': 'Filter by module',
|
|
102
|
-
'localization.key.select.module': 'Select or enter module',
|
|
103
|
-
'localization.key.enter.translation': 'Enter translation',
|
|
104
|
-
'localization.key.no.languages': 'No active languages configured',
|
|
105
|
-
'localization.key.empty': 'No translation keys found',
|
|
106
|
-
'localization.key.delete.title': 'Delete Translation Key',
|
|
107
|
-
'localization.key.readonly': 'System Key',
|
|
108
|
-
'localization.key.readonly.hint': 'System keys cannot be deleted',
|
|
109
|
-
// Translations
|
|
110
|
-
'localization.translation.title': 'Translations',
|
|
111
|
-
'localization.translation.manage': 'Manage Translations',
|
|
112
|
-
'localization.translation.value': 'Translation',
|
|
113
|
-
'localization.translation.verified': 'Verified',
|
|
114
|
-
'localization.translation.missing': 'Missing',
|
|
115
|
-
'localization.translation.save.changes': 'Save Changes',
|
|
116
|
-
'localization.translation.unsaved.changes': '{{count}} unsaved changes',
|
|
117
|
-
'localization.translation.no.keys': 'No translation keys found for this module',
|
|
118
|
-
'localization.translation.select.module': 'Select a module to view translations',
|
|
119
|
-
'localization.translation.select.language': 'Select a language to view translations',
|
|
120
|
-
'localization.translation.module': 'Module',
|
|
121
|
-
'localization.translation.language': 'Language',
|
|
122
|
-
'localization.translation.key': 'Key',
|
|
123
|
-
'localization.translation.default.message': 'Default Message',
|
|
124
|
-
// Language selector
|
|
125
|
-
'localization.selector.language': 'Language',
|
|
126
|
-
'localization.selector.select.language': 'Select Language',
|
|
127
|
-
// Translation list page
|
|
128
|
-
'localization.translation.save.success': 'Success',
|
|
129
|
-
'localization.translation.save.success.detail': 'Translations saved successfully',
|
|
130
|
-
'localization.translation.search.keys': 'Search translation keys...',
|
|
131
|
-
'localization.translation.select.module.hint': 'Please select a module to view its translations',
|
|
132
|
-
'localization.translation.select.language.hint': 'Please select a language to view translations',
|
|
133
|
-
'localization.translation.all.modules': 'All Modules',
|
|
134
|
-
'localization.translation.pagination': 'Showing {first} to {last} of {totalRecords} keys',
|
|
135
|
-
// Language direction labels
|
|
136
|
-
'localization.language.direction.ltr': 'Left to Right (LTR)',
|
|
137
|
-
'localization.language.direction.rtl': 'Right to Left (RTL)',
|
|
138
|
-
// Placeholders
|
|
139
|
-
'localization.placeholder.code': 'en',
|
|
140
|
-
'localization.placeholder.name': 'English',
|
|
141
|
-
'localization.placeholder.native.name': 'English',
|
|
142
|
-
'localization.placeholder.key.name': 'button.submit',
|
|
143
|
-
'localization.placeholder.default.message': 'Enter default value (English)',
|
|
144
|
-
'localization.placeholder.key.description': 'Optional description for translators',
|
|
145
54
|
// Language CRUD (API keys)
|
|
146
55
|
'language.create.success': 'Language created successfully',
|
|
147
56
|
'language.create.many.success': '{{count}} languages created successfully',
|
|
148
57
|
'language.get.success': 'Language retrieved successfully',
|
|
58
|
+
'language.get.by.ids.success': 'Languages retrieved successfully by Ids',
|
|
59
|
+
'language.get.by.filter.success': 'Languages retrieved successfully by filter',
|
|
149
60
|
'language.get.all.success': 'Languages retrieved successfully',
|
|
150
61
|
'language.update.success': 'Language updated successfully',
|
|
151
62
|
'language.update.many.success': '{{count}} languages updated successfully',
|
|
152
63
|
'language.delete.success': 'Language deleted successfully',
|
|
153
64
|
'language.restore.success': 'Language restored successfully',
|
|
154
|
-
'language.not.found': 'Language not found',
|
|
155
65
|
'language.active.success': 'Active languages retrieved successfully',
|
|
156
66
|
'language.set.default.success': 'Default language updated successfully',
|
|
157
67
|
'language.get.default.success': 'Default language retrieved successfully',
|
|
@@ -159,55 +69,90 @@ const LOCALIZATION_MESSAGES = {
|
|
|
159
69
|
'translation.key.create.success': 'Translation key created successfully',
|
|
160
70
|
'translation.key.create.many.success': '{{count}} translation keys created successfully',
|
|
161
71
|
'translation.key.get.success': 'Translation key retrieved successfully',
|
|
72
|
+
'translation.key.get.by.ids.success': 'Translation keys retrieved successfully by Ids',
|
|
73
|
+
'translation.key.get.by.filter.success': 'Translation keys retrieved successfully by filter',
|
|
162
74
|
'translation.key.get.all.success': 'Translation keys retrieved successfully',
|
|
163
75
|
'translation.key.update.success': 'Translation key updated successfully',
|
|
164
76
|
'translation.key.update.many.success': '{{count}} translation keys updated successfully',
|
|
165
77
|
'translation.key.delete.success': 'Translation key deleted successfully',
|
|
166
78
|
'translation.key.restore.success': 'Translation key restored successfully',
|
|
167
|
-
'translation.key.
|
|
168
|
-
'translation.key.import.success': 'Translation keys imported successfully',
|
|
169
|
-
'translation.key.export.success': 'Translation keys exported successfully',
|
|
79
|
+
'translation.key.modules.success': 'Modules retrieved successfully',
|
|
170
80
|
'translation.key.readonly.delete.forbidden': 'Cannot delete readonly translation keys: {{keys}}',
|
|
171
81
|
'translation.key.readonly.update.forbidden': 'Cannot modify key or module of system translation keys',
|
|
172
82
|
'translation.key.duplicate.key.in.module': 'Translation key "{{key}}" already exists in module "{{module}}"',
|
|
173
|
-
'translation.key.modules.success': 'Modules retrieved successfully',
|
|
174
83
|
// Translation CRUD (API keys)
|
|
175
84
|
'translation.create.success': 'Translation created successfully',
|
|
176
85
|
'translation.create.many.success': '{{count}} translations created successfully',
|
|
177
86
|
'translation.get.success': 'Translation retrieved successfully',
|
|
87
|
+
'translation.get.by.ids.success': 'Translations retrieved successfully by Ids',
|
|
88
|
+
'translation.get.by.filter.success': 'Translations retrieved successfully by filter',
|
|
178
89
|
'translation.get.all.success': 'Translations retrieved successfully',
|
|
179
90
|
'translation.update.success': 'Translation updated successfully',
|
|
180
91
|
'translation.update.many.success': '{{count}} translations updated successfully',
|
|
181
92
|
'translation.delete.success': 'Translation deleted successfully',
|
|
182
93
|
'translation.restore.success': 'Translation restored successfully',
|
|
183
|
-
'translation.not.found': 'Translation not found',
|
|
184
94
|
'translation.by.language.success': 'Translations retrieved successfully',
|
|
185
|
-
|
|
186
|
-
'
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
|
|
95
|
+
// pages/localization-container/localization-container.page.ts
|
|
96
|
+
'localization.title': 'Localization',
|
|
97
|
+
'localization.subtitle': 'Manage languages and translations',
|
|
98
|
+
'localization.tabs.languages': 'Languages',
|
|
99
|
+
'localization.tabs.keys': 'Keys',
|
|
100
|
+
// pages/language-list/language-list.page.ts
|
|
101
|
+
'localization.language.title': 'Languages',
|
|
102
|
+
'localization.language.subtitle': 'Manage available languages for your application',
|
|
103
|
+
'localization.language.new': 'Add Language',
|
|
104
|
+
'localization.language.code': 'Language Code',
|
|
105
|
+
'localization.language.name': 'Language Name',
|
|
106
|
+
'localization.language.native.name': 'Native Name',
|
|
107
|
+
'localization.language.direction': 'Text Direction',
|
|
108
|
+
'localization.language.rtl': 'RTL',
|
|
109
|
+
'localization.language.ltr': 'LTR',
|
|
110
|
+
'localization.language.default': 'Default',
|
|
111
|
+
'localization.language.set.default': 'Set as Default',
|
|
112
|
+
'localization.language.empty': 'No languages configured. Add a language to get started.',
|
|
113
|
+
'localization.language.confirm.set.default': 'Set "{{name}}" as the default language?',
|
|
114
|
+
'localization.language.delete.title': 'Delete Language',
|
|
115
|
+
// pages/language-form/language-form.page.ts
|
|
116
|
+
'localization.language.edit': 'Edit Language',
|
|
117
|
+
'localization.placeholder.code': 'en',
|
|
118
|
+
'localization.language.iso.code.hint': 'ISO 639-1 language code (e.g., en, ar, fr)',
|
|
119
|
+
'localization.placeholder.name': 'English',
|
|
120
|
+
'localization.placeholder.native.name': 'English',
|
|
121
|
+
'localization.language.native.name.hint': 'Name in the native language (e.g., العربية for Arabic)',
|
|
122
|
+
'localization.language.display.order': 'Display Order',
|
|
123
|
+
'localization.language.direction.ltr': 'Left to Right (LTR)',
|
|
124
|
+
'localization.language.direction.rtl': 'Right to Left (RTL)',
|
|
190
125
|
'localization.validation.code.required': 'Language code is required',
|
|
191
126
|
'localization.validation.code.max.length': 'Language code must be at most 10 characters',
|
|
192
127
|
'localization.validation.name.required': 'Language name is required',
|
|
193
128
|
'localization.validation.name.max.length': 'Language name must be at most 100 characters',
|
|
129
|
+
// pages/translation-key-list/translation-key-list.page.ts
|
|
130
|
+
'localization.key.title': 'Translation Keys',
|
|
131
|
+
'localization.key.subtitle': 'Manage translation keys for your application',
|
|
132
|
+
'localization.key.new': 'Add Key',
|
|
133
|
+
'localization.key.filter.module': 'Filter by module',
|
|
134
|
+
'localization.key.module': 'Module',
|
|
135
|
+
'localization.key.name': 'Key Name',
|
|
136
|
+
'localization.key.default.message': 'Default Message',
|
|
137
|
+
'localization.key.translations': 'Translations',
|
|
138
|
+
'localization.key.empty': 'No translation keys found',
|
|
139
|
+
'localization.key.delete.title': 'Delete Translation Key',
|
|
140
|
+
// pages/translation-key-form/translation-key-form.page.ts
|
|
141
|
+
'localization.key.edit': 'Edit Key',
|
|
142
|
+
'localization.key.about': 'Key Information',
|
|
143
|
+
'localization.placeholder.key.name': 'button.submit',
|
|
144
|
+
'localization.key.select.module': 'Select or enter module',
|
|
145
|
+
'localization.placeholder.default.message': 'Enter default value (English)',
|
|
146
|
+
'localization.key.description': 'Description',
|
|
147
|
+
'localization.placeholder.key.description': 'Optional description for translators',
|
|
148
|
+
'localization.key.variables': 'Variables',
|
|
149
|
+
'localization.key.variables.placeholder': 'e.g., name, count, date',
|
|
150
|
+
'localization.key.variables.hint': 'Enter variable names used in this translation',
|
|
151
|
+
'localization.key.translations.section': 'Translations',
|
|
152
|
+
'localization.key.no.languages': 'No active languages configured',
|
|
153
|
+
'localization.key.enter.translation': 'Enter translation',
|
|
194
154
|
'localization.validation.key.required': 'Translation key is required',
|
|
195
|
-
'localization.validation.module.required': 'Module is required',
|
|
196
155
|
'localization.validation.default.message.required': 'Default message is required',
|
|
197
|
-
// Additional success messages
|
|
198
|
-
'localization.key.create.success': 'Translation key created successfully',
|
|
199
|
-
'localization.key.update.success': 'Translation key updated successfully',
|
|
200
|
-
'localization.key.delete.success': 'Translation key deleted successfully',
|
|
201
|
-
'localization.language.delete.success': 'Language deleted successfully',
|
|
202
|
-
'localization.language.load.failed': 'Failed to load languages',
|
|
203
|
-
'localization.key.load.failed': 'Failed to load translation keys',
|
|
204
|
-
// Translation key operation keys (used by form components)
|
|
205
|
-
'localization.translation.key.create.success': 'Translation key created successfully',
|
|
206
|
-
'localization.translation.key.update.success': 'Translation key updated successfully',
|
|
207
|
-
'localization.translation.key.delete.success': 'Translation key deleted successfully',
|
|
208
|
-
// Pagination templates
|
|
209
|
-
'localization.pagination.languages.template': 'Showing {first} to {last} of {totalRecords} languages',
|
|
210
|
-
'localization.pagination.keys.template': 'Showing {first} to {last} of {totalRecords} keys',
|
|
211
156
|
};
|
|
212
157
|
|
|
213
158
|
class LocalizationStateService {
|
|
@@ -255,8 +200,16 @@ class LocalizationStateService {
|
|
|
255
200
|
dotToCamel(str) {
|
|
256
201
|
return str.replace(/\.([a-z])/g, (_, c) => c.toUpperCase());
|
|
257
202
|
}
|
|
203
|
+
PRIMENG_NUMERIC_KEYS = new Set(['firstDayOfWeek']);
|
|
204
|
+
PRIMENG_ARRAY_DEFAULTS = {
|
|
205
|
+
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
206
|
+
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
207
|
+
dayNamesMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
|
|
208
|
+
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
|
209
|
+
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
210
|
+
};
|
|
258
211
|
syncPrimeNGTranslations(translations, fallbacks) {
|
|
259
|
-
const primeNGTranslations = {};
|
|
212
|
+
const primeNGTranslations = { ...this.PRIMENG_ARRAY_DEFAULTS };
|
|
260
213
|
const ariaTranslations = {};
|
|
261
214
|
const prefix = 'primeng.';
|
|
262
215
|
const ariaPrefix = 'primeng.aria.';
|
|
@@ -268,15 +221,13 @@ class LocalizationStateService {
|
|
|
268
221
|
}
|
|
269
222
|
else if (key.startsWith(prefix)) {
|
|
270
223
|
const primeKey = this.dotToCamel(key.substring(prefix.length));
|
|
271
|
-
primeNGTranslations[primeKey] = value;
|
|
224
|
+
primeNGTranslations[primeKey] = this.PRIMENG_NUMERIC_KEYS.has(primeKey) ? parseInt(value, 10) : value;
|
|
272
225
|
}
|
|
273
226
|
}
|
|
274
227
|
if (Object.keys(ariaTranslations).length > 0) {
|
|
275
228
|
primeNGTranslations['aria'] = ariaTranslations;
|
|
276
229
|
}
|
|
277
|
-
|
|
278
|
-
this.primeNG.setTranslation(primeNGTranslations);
|
|
279
|
-
}
|
|
230
|
+
this.primeNG.setTranslation(primeNGTranslations);
|
|
280
231
|
}
|
|
281
232
|
setCurrentLanguage(language) {
|
|
282
233
|
this._currentLanguage.set(language);
|
|
@@ -393,7 +344,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
393
344
|
|
|
394
345
|
class TranslateService {
|
|
395
346
|
localizationState = inject(LocalizationStateService);
|
|
396
|
-
localizationConfig = inject(LOCALIZATION_CONFIG, {
|
|
347
|
+
localizationConfig = inject(LOCALIZATION_CONFIG, {
|
|
348
|
+
optional: true,
|
|
349
|
+
});
|
|
397
350
|
languageCode = this.localizationState.currentLanguageCode;
|
|
398
351
|
translate(key, params) {
|
|
399
352
|
if (!this.localizationConfig) {
|
|
@@ -412,9 +365,6 @@ class TranslateService {
|
|
|
412
365
|
return this.translate(key, params);
|
|
413
366
|
});
|
|
414
367
|
}
|
|
415
|
-
instant(key, params) {
|
|
416
|
-
return this.translate(key, params);
|
|
417
|
-
}
|
|
418
368
|
interpolate(template, params) {
|
|
419
369
|
if (!params || !template)
|
|
420
370
|
return template;
|
|
@@ -507,30 +457,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
507
457
|
args: [{ providedIn: 'root' }]
|
|
508
458
|
}] });
|
|
509
459
|
|
|
510
|
-
class LanguageApiService {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
get baseUrl() {
|
|
514
|
-
return `${this.appConfig.apiBaseUrl}/localization/language`;
|
|
515
|
-
}
|
|
516
|
-
getAll() {
|
|
517
|
-
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
518
|
-
pagination: { currentPage: 0, pageSize: 100 },
|
|
519
|
-
filter: {},
|
|
520
|
-
sort: { serial: 'ASC', name: 'ASC' },
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
getById(id) {
|
|
524
|
-
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
525
|
-
}
|
|
526
|
-
create(dto) {
|
|
527
|
-
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
528
|
-
}
|
|
529
|
-
update(dto) {
|
|
530
|
-
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
531
|
-
}
|
|
532
|
-
delete(id) {
|
|
533
|
-
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
460
|
+
class LanguageApiService extends ApiResourceService {
|
|
461
|
+
constructor() {
|
|
462
|
+
super('language', inject(HttpClient), 'localization');
|
|
534
463
|
}
|
|
535
464
|
setDefault(id) {
|
|
536
465
|
return this.http.post(`${this.baseUrl}/set-default`, { id });
|
|
@@ -541,57 +470,26 @@ class LanguageApiService {
|
|
|
541
470
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageApiService, decorators: [{
|
|
542
471
|
type: Injectable,
|
|
543
472
|
args: [{ providedIn: 'root' }]
|
|
544
|
-
}] });
|
|
473
|
+
}], ctorParameters: () => [] });
|
|
545
474
|
|
|
546
|
-
class TranslationKeyApiService {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
get baseUrl() {
|
|
550
|
-
return `${this.appConfig.apiBaseUrl}/localization/translation-key`;
|
|
551
|
-
}
|
|
552
|
-
getAll(filter = {}) {
|
|
553
|
-
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
554
|
-
pagination: { currentPage: 0, pageSize: 1000 },
|
|
555
|
-
filter,
|
|
556
|
-
sort: { module: 'ASC', key: 'ASC' },
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
getByModule(module) {
|
|
560
|
-
return this.http.post(`${this.baseUrl}/get-by-module`, {
|
|
561
|
-
module,
|
|
562
|
-
});
|
|
475
|
+
class TranslationKeyApiService extends ApiResourceService {
|
|
476
|
+
constructor() {
|
|
477
|
+
super('translation-key', inject(HttpClient), 'localization');
|
|
563
478
|
}
|
|
564
479
|
getModules() {
|
|
565
480
|
return this.http.post(`${this.baseUrl}/get-modules`, {});
|
|
566
481
|
}
|
|
567
|
-
getById(id) {
|
|
568
|
-
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
569
|
-
}
|
|
570
|
-
create(dto) {
|
|
571
|
-
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
572
|
-
}
|
|
573
|
-
createMany(dtos) {
|
|
574
|
-
return this.http.post(`${this.baseUrl}/insert-many`, { items: dtos });
|
|
575
|
-
}
|
|
576
|
-
update(dto) {
|
|
577
|
-
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
578
|
-
}
|
|
579
|
-
delete(id) {
|
|
580
|
-
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
581
|
-
}
|
|
582
482
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
583
483
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, providedIn: 'root' });
|
|
584
484
|
}
|
|
585
485
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyApiService, decorators: [{
|
|
586
486
|
type: Injectable,
|
|
587
487
|
args: [{ providedIn: 'root' }]
|
|
588
|
-
}] });
|
|
488
|
+
}], ctorParameters: () => [] });
|
|
589
489
|
|
|
590
|
-
class TranslationApiService {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
get baseUrl() {
|
|
594
|
-
return `${this.appConfig.apiBaseUrl}/localization/translation`;
|
|
490
|
+
class TranslationApiService extends ApiResourceService {
|
|
491
|
+
constructor() {
|
|
492
|
+
super('translation', inject(HttpClient), 'localization');
|
|
595
493
|
}
|
|
596
494
|
getByLanguageId(languageId) {
|
|
597
495
|
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
@@ -607,21 +505,6 @@ class TranslationApiService {
|
|
|
607
505
|
sort: {},
|
|
608
506
|
});
|
|
609
507
|
}
|
|
610
|
-
getById(id) {
|
|
611
|
-
return this.http.post(`${this.baseUrl}/get/${id}`, {});
|
|
612
|
-
}
|
|
613
|
-
create(dto) {
|
|
614
|
-
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
615
|
-
}
|
|
616
|
-
update(dto) {
|
|
617
|
-
return this.http.post(`${this.baseUrl}/update`, dto);
|
|
618
|
-
}
|
|
619
|
-
bulkUpdate(translations) {
|
|
620
|
-
return this.http.post(`${this.baseUrl}/update-many-values`, { translations });
|
|
621
|
-
}
|
|
622
|
-
delete(id) {
|
|
623
|
-
return this.http.post(`${this.baseUrl}/delete`, { id, type: 'delete' });
|
|
624
|
-
}
|
|
625
508
|
getByKeyId(translationKeyId) {
|
|
626
509
|
return this.http.post(`${this.baseUrl}/get-all`, {
|
|
627
510
|
pagination: { currentPage: 0, pageSize: 1000 },
|
|
@@ -632,13 +515,16 @@ class TranslationApiService {
|
|
|
632
515
|
getCounts() {
|
|
633
516
|
return this.http.post(`${this.baseUrl}/get-counts`, {});
|
|
634
517
|
}
|
|
518
|
+
bulkUpdate(translations) {
|
|
519
|
+
return this.http.post(`${this.baseUrl}/update-many-values`, { translations });
|
|
520
|
+
}
|
|
635
521
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
636
522
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, providedIn: 'root' });
|
|
637
523
|
}
|
|
638
524
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationApiService, decorators: [{
|
|
639
525
|
type: Injectable,
|
|
640
526
|
args: [{ providedIn: 'root' }]
|
|
641
|
-
}] });
|
|
527
|
+
}], ctorParameters: () => [] });
|
|
642
528
|
|
|
643
529
|
class LanguageSelectorComponent {
|
|
644
530
|
localizationState = inject(LocalizationStateService);
|
|
@@ -885,10 +771,6 @@ const LOCALIZATION_ROUTES = [
|
|
|
885
771
|
path: 'keys/:id',
|
|
886
772
|
loadComponent: () => Promise.resolve().then(function () { return translationKeyForm_page; }).then((m) => m.TranslationKeyFormPage),
|
|
887
773
|
},
|
|
888
|
-
{
|
|
889
|
-
path: 'translations',
|
|
890
|
-
loadComponent: () => Promise.resolve().then(function () { return translationList_page; }).then((m) => m.TranslationListPage),
|
|
891
|
-
},
|
|
892
774
|
{
|
|
893
775
|
path: '',
|
|
894
776
|
redirectTo: 'languages',
|
|
@@ -915,13 +797,6 @@ class LocalizationContainerPage {
|
|
|
915
797
|
route: 'keys',
|
|
916
798
|
permission: TRANSLATION_KEY_PERMISSIONS.READ,
|
|
917
799
|
},
|
|
918
|
-
{
|
|
919
|
-
id: 'translations',
|
|
920
|
-
labelKey: 'localization.tabs.translations',
|
|
921
|
-
icon: 'pi pi-language',
|
|
922
|
-
route: 'translations',
|
|
923
|
-
permission: TRANSLATION_PERMISSIONS.READ,
|
|
924
|
-
},
|
|
925
800
|
];
|
|
926
801
|
visibleTabs = computed(() => {
|
|
927
802
|
// Explicitly track permissions signal for reactivity
|
|
@@ -995,10 +870,12 @@ class LanguageListPage {
|
|
|
995
870
|
messageService = inject(MessageService);
|
|
996
871
|
translateService = inject(TranslateService);
|
|
997
872
|
destroyRef = inject(DestroyRef);
|
|
998
|
-
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
999
|
-
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
1000
873
|
ngOnInit() {
|
|
1001
|
-
this.
|
|
874
|
+
this.languageService.fetchList('', {
|
|
875
|
+
pagination: { currentPage: 0, pageSize: 100 },
|
|
876
|
+
filter: {},
|
|
877
|
+
sort: { serial: 'ASC', name: 'ASC' },
|
|
878
|
+
});
|
|
1002
879
|
}
|
|
1003
880
|
onCreate() {
|
|
1004
881
|
this.router.navigate(['/localization/languages/new']);
|
|
@@ -1006,29 +883,14 @@ class LanguageListPage {
|
|
|
1006
883
|
onEdit(id) {
|
|
1007
884
|
this.router.navigate(['/localization/languages', id]);
|
|
1008
885
|
}
|
|
1009
|
-
loadLanguages() {
|
|
1010
|
-
this.isLoading.set(true);
|
|
1011
|
-
this.languageService.getAll()
|
|
1012
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1013
|
-
.subscribe({
|
|
1014
|
-
next: (response) => {
|
|
1015
|
-
if (response.success) {
|
|
1016
|
-
this.languages.set(response.data ?? []);
|
|
1017
|
-
}
|
|
1018
|
-
this.isLoading.set(false);
|
|
1019
|
-
},
|
|
1020
|
-
error: () => {
|
|
1021
|
-
this.isLoading.set(false);
|
|
1022
|
-
},
|
|
1023
|
-
});
|
|
1024
|
-
}
|
|
1025
886
|
onSetDefault(lang) {
|
|
1026
887
|
this.confirmationService.confirm({
|
|
1027
888
|
message: this.translateService.translate('localization.language.confirm.set.default', { name: lang.name }),
|
|
1028
889
|
header: this.translateService.translate('localization.language.set.default'),
|
|
1029
890
|
icon: 'pi pi-star',
|
|
1030
891
|
accept: () => {
|
|
1031
|
-
this.languageService
|
|
892
|
+
this.languageService
|
|
893
|
+
.setDefault(lang.id)
|
|
1032
894
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1033
895
|
.subscribe({
|
|
1034
896
|
next: (response) => {
|
|
@@ -1036,9 +898,11 @@ class LanguageListPage {
|
|
|
1036
898
|
this.messageService.add({
|
|
1037
899
|
severity: 'success',
|
|
1038
900
|
summary: this.translateService.translate('shared.success'),
|
|
1039
|
-
detail:
|
|
901
|
+
detail: response.messageKey
|
|
902
|
+
? this.translateService.translate(response.messageKey, response.messageVariables)
|
|
903
|
+
: (response.message ?? ''),
|
|
1040
904
|
});
|
|
1041
|
-
this.
|
|
905
|
+
this.languageService.reload();
|
|
1042
906
|
}
|
|
1043
907
|
},
|
|
1044
908
|
});
|
|
@@ -1052,7 +916,7 @@ class LanguageListPage {
|
|
|
1052
916
|
icon: 'pi pi-exclamation-triangle',
|
|
1053
917
|
acceptButtonStyleClass: 'p-button-danger',
|
|
1054
918
|
accept: () => {
|
|
1055
|
-
this.languageService.delete(lang.id)
|
|
919
|
+
from(this.languageService.delete({ id: lang.id, type: 'delete' }))
|
|
1056
920
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1057
921
|
.subscribe({
|
|
1058
922
|
next: (response) => {
|
|
@@ -1060,9 +924,11 @@ class LanguageListPage {
|
|
|
1060
924
|
this.messageService.add({
|
|
1061
925
|
severity: 'success',
|
|
1062
926
|
summary: this.translateService.translate('shared.success'),
|
|
1063
|
-
detail:
|
|
927
|
+
detail: response.messageKey
|
|
928
|
+
? this.translateService.translate(response.messageKey, response.messageVariables)
|
|
929
|
+
: (response.message ?? ''),
|
|
1064
930
|
});
|
|
1065
|
-
this.
|
|
931
|
+
this.languageService.reload();
|
|
1066
932
|
}
|
|
1067
933
|
},
|
|
1068
934
|
});
|
|
@@ -1072,16 +938,20 @@ class LanguageListPage {
|
|
|
1072
938
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageListPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1073
939
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: LanguageListPage, isStandalone: true, selector: "lib-language-list-page", providers: [ConfirmationService, MessageService], ngImport: i0, template: `
|
|
1074
940
|
<div class="card">
|
|
1075
|
-
<div
|
|
941
|
+
<div
|
|
942
|
+
class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
|
|
943
|
+
>
|
|
1076
944
|
<div>
|
|
1077
|
-
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
945
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
946
|
+
{{ 'localization.language.title' | translate }}
|
|
947
|
+
</h3>
|
|
1078
948
|
<p class="text-sm text-muted-color mt-1">
|
|
1079
949
|
{{ 'localization.language.subtitle' | translate }}
|
|
1080
950
|
</p>
|
|
1081
951
|
</div>
|
|
1082
952
|
<p-button
|
|
1083
953
|
*hasPermission="LANGUAGE_PERMISSIONS.CREATE"
|
|
1084
|
-
[label]="'localization.language.
|
|
954
|
+
[label]="'localization.language.new' | translate"
|
|
1085
955
|
icon="pi pi-plus"
|
|
1086
956
|
(onClick)="onCreate()"
|
|
1087
957
|
styleClass="w-full sm:w-auto"
|
|
@@ -1090,8 +960,8 @@ class LanguageListPage {
|
|
|
1090
960
|
|
|
1091
961
|
<div class="overflow-x-auto -mx-4 sm:mx-0">
|
|
1092
962
|
<p-table
|
|
1093
|
-
[value]="
|
|
1094
|
-
[loading]="isLoading()"
|
|
963
|
+
[value]="languageService.data()"
|
|
964
|
+
[loading]="languageService.isLoading()"
|
|
1095
965
|
styleClass="p-datatable-sm"
|
|
1096
966
|
[tableStyle]="{ 'min-width': '40rem' }"
|
|
1097
967
|
>
|
|
@@ -1115,18 +985,29 @@ class LanguageListPage {
|
|
|
1115
985
|
<td>{{ lang.nativeName || ('shared.na' | translate) }}</td>
|
|
1116
986
|
<td>
|
|
1117
987
|
<p-tag
|
|
1118
|
-
[value]="
|
|
988
|
+
[value]="
|
|
989
|
+
lang.direction === 'rtl'
|
|
990
|
+
? ('localization.language.rtl' | translate)
|
|
991
|
+
: ('localization.language.ltr' | translate)
|
|
992
|
+
"
|
|
1119
993
|
[severity]="lang.direction === 'rtl' ? 'warn' : 'info'"
|
|
1120
994
|
/>
|
|
1121
995
|
</td>
|
|
1122
996
|
<td>
|
|
1123
997
|
<div class="flex gap-1 items-center">
|
|
1124
998
|
<p-tag
|
|
1125
|
-
[value]="
|
|
999
|
+
[value]="
|
|
1000
|
+
lang.isActive
|
|
1001
|
+
? ('shared.active' | translate)
|
|
1002
|
+
: ('shared.inactive' | translate)
|
|
1003
|
+
"
|
|
1126
1004
|
[severity]="lang.isActive ? 'success' : 'secondary'"
|
|
1127
1005
|
/>
|
|
1128
1006
|
@if (lang.isDefault) {
|
|
1129
|
-
<p-tag
|
|
1007
|
+
<p-tag
|
|
1008
|
+
[value]="'localization.language.default' | translate"
|
|
1009
|
+
severity="contrast"
|
|
1010
|
+
/>
|
|
1130
1011
|
}
|
|
1131
1012
|
</div>
|
|
1132
1013
|
</td>
|
|
@@ -1138,7 +1019,9 @@ class LanguageListPage {
|
|
|
1138
1019
|
icon="pi pi-star"
|
|
1139
1020
|
[text]="true"
|
|
1140
1021
|
size="small"
|
|
1141
|
-
[pTooltip]="
|
|
1022
|
+
[pTooltip]="
|
|
1023
|
+
'localization.language.set.default' | translate
|
|
1024
|
+
"
|
|
1142
1025
|
(onClick)="onSetDefault(lang)"
|
|
1143
1026
|
/>
|
|
1144
1027
|
}
|
|
@@ -1179,7 +1062,7 @@ class LanguageListPage {
|
|
|
1179
1062
|
|
|
1180
1063
|
<p-confirmDialog />
|
|
1181
1064
|
<p-toast />
|
|
1182
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type:
|
|
1065
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1183
1066
|
}
|
|
1184
1067
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageListPage, decorators: [{
|
|
1185
1068
|
type: Component,
|
|
@@ -1189,16 +1072,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1189
1072
|
providers: [ConfirmationService, MessageService],
|
|
1190
1073
|
template: `
|
|
1191
1074
|
<div class="card">
|
|
1192
|
-
<div
|
|
1075
|
+
<div
|
|
1076
|
+
class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
|
|
1077
|
+
>
|
|
1193
1078
|
<div>
|
|
1194
|
-
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1079
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1080
|
+
{{ 'localization.language.title' | translate }}
|
|
1081
|
+
</h3>
|
|
1195
1082
|
<p class="text-sm text-muted-color mt-1">
|
|
1196
1083
|
{{ 'localization.language.subtitle' | translate }}
|
|
1197
1084
|
</p>
|
|
1198
1085
|
</div>
|
|
1199
1086
|
<p-button
|
|
1200
1087
|
*hasPermission="LANGUAGE_PERMISSIONS.CREATE"
|
|
1201
|
-
[label]="'localization.language.
|
|
1088
|
+
[label]="'localization.language.new' | translate"
|
|
1202
1089
|
icon="pi pi-plus"
|
|
1203
1090
|
(onClick)="onCreate()"
|
|
1204
1091
|
styleClass="w-full sm:w-auto"
|
|
@@ -1207,8 +1094,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1207
1094
|
|
|
1208
1095
|
<div class="overflow-x-auto -mx-4 sm:mx-0">
|
|
1209
1096
|
<p-table
|
|
1210
|
-
[value]="
|
|
1211
|
-
[loading]="isLoading()"
|
|
1097
|
+
[value]="languageService.data()"
|
|
1098
|
+
[loading]="languageService.isLoading()"
|
|
1212
1099
|
styleClass="p-datatable-sm"
|
|
1213
1100
|
[tableStyle]="{ 'min-width': '40rem' }"
|
|
1214
1101
|
>
|
|
@@ -1232,18 +1119,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1232
1119
|
<td>{{ lang.nativeName || ('shared.na' | translate) }}</td>
|
|
1233
1120
|
<td>
|
|
1234
1121
|
<p-tag
|
|
1235
|
-
[value]="
|
|
1122
|
+
[value]="
|
|
1123
|
+
lang.direction === 'rtl'
|
|
1124
|
+
? ('localization.language.rtl' | translate)
|
|
1125
|
+
: ('localization.language.ltr' | translate)
|
|
1126
|
+
"
|
|
1236
1127
|
[severity]="lang.direction === 'rtl' ? 'warn' : 'info'"
|
|
1237
1128
|
/>
|
|
1238
1129
|
</td>
|
|
1239
1130
|
<td>
|
|
1240
1131
|
<div class="flex gap-1 items-center">
|
|
1241
1132
|
<p-tag
|
|
1242
|
-
[value]="
|
|
1133
|
+
[value]="
|
|
1134
|
+
lang.isActive
|
|
1135
|
+
? ('shared.active' | translate)
|
|
1136
|
+
: ('shared.inactive' | translate)
|
|
1137
|
+
"
|
|
1243
1138
|
[severity]="lang.isActive ? 'success' : 'secondary'"
|
|
1244
1139
|
/>
|
|
1245
1140
|
@if (lang.isDefault) {
|
|
1246
|
-
<p-tag
|
|
1141
|
+
<p-tag
|
|
1142
|
+
[value]="'localization.language.default' | translate"
|
|
1143
|
+
severity="contrast"
|
|
1144
|
+
/>
|
|
1247
1145
|
}
|
|
1248
1146
|
</div>
|
|
1249
1147
|
</td>
|
|
@@ -1255,7 +1153,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1255
1153
|
icon="pi pi-star"
|
|
1256
1154
|
[text]="true"
|
|
1257
1155
|
size="small"
|
|
1258
|
-
[pTooltip]="
|
|
1156
|
+
[pTooltip]="
|
|
1157
|
+
'localization.language.set.default' | translate
|
|
1158
|
+
"
|
|
1259
1159
|
(onClick)="onSetDefault(lang)"
|
|
1260
1160
|
/>
|
|
1261
1161
|
}
|
|
@@ -1310,19 +1210,27 @@ class LanguageFormPage {
|
|
|
1310
1210
|
route = inject(ActivatedRoute);
|
|
1311
1211
|
languageService = inject(LanguageApiService);
|
|
1312
1212
|
messageService = inject(MessageService);
|
|
1313
|
-
translateAdapter = inject(TRANSLATE_ADAPTER, {
|
|
1213
|
+
translateAdapter = inject(TRANSLATE_ADAPTER, {
|
|
1214
|
+
optional: true,
|
|
1215
|
+
});
|
|
1314
1216
|
destroyRef = inject(DestroyRef);
|
|
1315
1217
|
routeParams = toSignal(this.route.paramMap);
|
|
1316
1218
|
loadTriggered = false;
|
|
1317
1219
|
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
1318
1220
|
existingLanguage = signal(null, ...(ngDevMode ? [{ debugName: "existingLanguage" }] : []));
|
|
1319
1221
|
isEditMode = computed(() => !!this.existingLanguage(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
1320
|
-
translate(key) {
|
|
1321
|
-
return this.translateAdapter?.translate(key) ?? key;
|
|
1222
|
+
translate(key, vars) {
|
|
1223
|
+
return this.translateAdapter?.translate(key, vars) ?? key;
|
|
1322
1224
|
}
|
|
1323
1225
|
directionOptions = computed(() => [
|
|
1324
|
-
{
|
|
1325
|
-
|
|
1226
|
+
{
|
|
1227
|
+
label: this.translate('localization.language.direction.ltr'),
|
|
1228
|
+
value: 'ltr',
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
label: this.translate('localization.language.direction.rtl'),
|
|
1232
|
+
value: 'rtl',
|
|
1233
|
+
},
|
|
1326
1234
|
], ...(ngDevMode ? [{ debugName: "directionOptions" }] : []));
|
|
1327
1235
|
formModel = signal({
|
|
1328
1236
|
code: '',
|
|
@@ -1334,10 +1242,18 @@ class LanguageFormPage {
|
|
|
1334
1242
|
isDefault: false,
|
|
1335
1243
|
}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
1336
1244
|
formTree = form(this.formModel, (f) => {
|
|
1337
|
-
required(f.code, {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
maxLength(f.
|
|
1245
|
+
required(f.code, {
|
|
1246
|
+
message: this.translate('localization.validation.code.required'),
|
|
1247
|
+
});
|
|
1248
|
+
maxLength(f.code, 10, {
|
|
1249
|
+
message: this.translate('localization.validation.code.max.length'),
|
|
1250
|
+
});
|
|
1251
|
+
required(f.name, {
|
|
1252
|
+
message: this.translate('localization.validation.name.required'),
|
|
1253
|
+
});
|
|
1254
|
+
maxLength(f.name, 100, {
|
|
1255
|
+
message: this.translate('localization.validation.name.max.length'),
|
|
1256
|
+
});
|
|
1341
1257
|
});
|
|
1342
1258
|
isFormValid = computed(() => {
|
|
1343
1259
|
const model = this.formModel();
|
|
@@ -1360,7 +1276,7 @@ class LanguageFormPage {
|
|
|
1360
1276
|
}
|
|
1361
1277
|
loadLanguage(id) {
|
|
1362
1278
|
this.isSaving.set(true);
|
|
1363
|
-
this.languageService.
|
|
1279
|
+
from(this.languageService.findById(id))
|
|
1364
1280
|
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
1365
1281
|
.subscribe({
|
|
1366
1282
|
next: (response) => {
|
|
@@ -1398,8 +1314,11 @@ class LanguageFormPage {
|
|
|
1398
1314
|
isDefault: model.isDefault,
|
|
1399
1315
|
};
|
|
1400
1316
|
const operation$ = this.isEditMode()
|
|
1401
|
-
? this.languageService.update({
|
|
1402
|
-
|
|
1317
|
+
? from(this.languageService.update({
|
|
1318
|
+
id: this.existingLanguage().id,
|
|
1319
|
+
...dto,
|
|
1320
|
+
}))
|
|
1321
|
+
: from(this.languageService.insert(dto));
|
|
1403
1322
|
operation$
|
|
1404
1323
|
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
1405
1324
|
.subscribe({
|
|
@@ -1408,7 +1327,9 @@ class LanguageFormPage {
|
|
|
1408
1327
|
this.messageService.add({
|
|
1409
1328
|
severity: 'success',
|
|
1410
1329
|
summary: this.translate('shared.success'),
|
|
1411
|
-
detail:
|
|
1330
|
+
detail: response.messageKey
|
|
1331
|
+
? this.translate(response.messageKey, response.messageVariables)
|
|
1332
|
+
: (response.message ?? ''),
|
|
1412
1333
|
});
|
|
1413
1334
|
this.router.navigate(['/localization/languages']);
|
|
1414
1335
|
}
|
|
@@ -1424,67 +1345,93 @@ class LanguageFormPage {
|
|
|
1424
1345
|
<ng-template #header>
|
|
1425
1346
|
<div class="flex justify-between items-center p-4">
|
|
1426
1347
|
<h2 class="text-xl font-semibold m-0">
|
|
1427
|
-
{{
|
|
1348
|
+
{{
|
|
1349
|
+
isEditMode()
|
|
1350
|
+
? ('localization.language.edit' | translate)
|
|
1351
|
+
: ('localization.language.new' | translate)
|
|
1352
|
+
}}
|
|
1428
1353
|
</h2>
|
|
1429
1354
|
</div>
|
|
1430
1355
|
</ng-template>
|
|
1431
1356
|
|
|
1432
|
-
<form
|
|
1357
|
+
<form
|
|
1358
|
+
(ngSubmit)="onSubmit()"
|
|
1359
|
+
class="grid grid-cols-1 md:grid-cols-2 gap-4"
|
|
1360
|
+
>
|
|
1433
1361
|
<!-- Language Code -->
|
|
1434
1362
|
<div class="flex flex-col gap-2">
|
|
1435
|
-
<label for="code" class="font-medium"
|
|
1363
|
+
<label for="code" class="font-medium"
|
|
1364
|
+
>{{ 'localization.language.code' | translate }} *</label
|
|
1365
|
+
>
|
|
1436
1366
|
<input
|
|
1437
1367
|
pInputText
|
|
1438
1368
|
id="code"
|
|
1439
1369
|
[formField]="formTree.code"
|
|
1440
|
-
[placeholder]="'localization.placeholder.code' | translate"
|
|
1441
|
-
|
|
1370
|
+
[placeholder]="'localization.placeholder.code' | translate"
|
|
1371
|
+
/>
|
|
1372
|
+
<small class="text-muted-color">{{
|
|
1373
|
+
'localization.language.iso.code.hint' | translate
|
|
1374
|
+
}}</small>
|
|
1442
1375
|
</div>
|
|
1443
1376
|
|
|
1444
1377
|
<!-- Language Name -->
|
|
1445
1378
|
<div class="flex flex-col gap-2">
|
|
1446
|
-
<label for="name" class="font-medium"
|
|
1379
|
+
<label for="name" class="font-medium"
|
|
1380
|
+
>{{ 'localization.language.name' | translate }} *</label
|
|
1381
|
+
>
|
|
1447
1382
|
<input
|
|
1448
1383
|
pInputText
|
|
1449
1384
|
id="name"
|
|
1450
1385
|
[formField]="formTree.name"
|
|
1451
|
-
[placeholder]="'localization.placeholder.name' | translate"
|
|
1386
|
+
[placeholder]="'localization.placeholder.name' | translate"
|
|
1387
|
+
/>
|
|
1452
1388
|
</div>
|
|
1453
1389
|
|
|
1454
1390
|
<!-- Native Name -->
|
|
1455
1391
|
<div class="flex flex-col gap-2">
|
|
1456
|
-
<label for="nativeName" class="font-medium">{{
|
|
1392
|
+
<label for="nativeName" class="font-medium">{{
|
|
1393
|
+
'localization.language.native.name' | translate
|
|
1394
|
+
}}</label>
|
|
1457
1395
|
<input
|
|
1458
1396
|
pInputText
|
|
1459
1397
|
id="nativeName"
|
|
1460
1398
|
[formField]="formTree.nativeName"
|
|
1461
|
-
[placeholder]="'localization.placeholder.native.name' | translate"
|
|
1462
|
-
|
|
1399
|
+
[placeholder]="'localization.placeholder.native.name' | translate"
|
|
1400
|
+
/>
|
|
1401
|
+
<small class="text-muted-color">{{
|
|
1402
|
+
'localization.language.native.name.hint' | translate
|
|
1403
|
+
}}</small>
|
|
1463
1404
|
</div>
|
|
1464
1405
|
|
|
1465
1406
|
<!-- Text Direction -->
|
|
1466
1407
|
<div class="flex flex-col gap-2">
|
|
1467
|
-
<label for="direction" class="font-medium"
|
|
1408
|
+
<label for="direction" class="font-medium"
|
|
1409
|
+
>{{ 'localization.language.direction' | translate }} *</label
|
|
1410
|
+
>
|
|
1468
1411
|
<p-select
|
|
1469
1412
|
id="direction"
|
|
1470
1413
|
[ngModel]="formModel().direction"
|
|
1471
1414
|
(ngModelChange)="updateDirection($event)"
|
|
1472
|
-
[ngModelOptions]="{standalone: true}"
|
|
1415
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1473
1416
|
[options]="directionOptions()"
|
|
1474
1417
|
optionLabel="label"
|
|
1475
1418
|
optionValue="value"
|
|
1476
|
-
class="w-full"
|
|
1419
|
+
class="w-full"
|
|
1420
|
+
/>
|
|
1477
1421
|
</div>
|
|
1478
1422
|
|
|
1479
1423
|
<!-- Display Order -->
|
|
1480
1424
|
<div class="flex flex-col gap-2">
|
|
1481
|
-
<label for="serial" class="font-medium">{{
|
|
1425
|
+
<label for="serial" class="font-medium">{{
|
|
1426
|
+
'localization.language.display.order' | translate
|
|
1427
|
+
}}</label>
|
|
1482
1428
|
<input
|
|
1483
1429
|
pInputText
|
|
1484
1430
|
id="serial"
|
|
1485
1431
|
type="number"
|
|
1486
1432
|
[formField]="formTree.serial"
|
|
1487
|
-
[placeholder]="'shared.display.order.placeholder' | translate"
|
|
1433
|
+
[placeholder]="'shared.display.order.placeholder' | translate"
|
|
1434
|
+
/>
|
|
1488
1435
|
</div>
|
|
1489
1436
|
|
|
1490
1437
|
<!-- Empty cell for alignment -->
|
|
@@ -1508,18 +1455,24 @@ class LanguageFormPage {
|
|
|
1508
1455
|
[label]="'shared.cancel' | translate"
|
|
1509
1456
|
severity="secondary"
|
|
1510
1457
|
[outlined]="true"
|
|
1511
|
-
(onClick)="onCancel()"
|
|
1458
|
+
(onClick)="onCancel()"
|
|
1459
|
+
/>
|
|
1512
1460
|
<p-button
|
|
1513
|
-
[label]="
|
|
1461
|
+
[label]="
|
|
1462
|
+
isEditMode()
|
|
1463
|
+
? ('shared.update' | translate)
|
|
1464
|
+
: ('shared.create' | translate)
|
|
1465
|
+
"
|
|
1514
1466
|
type="submit"
|
|
1515
1467
|
[loading]="isSaving()"
|
|
1516
|
-
[disabled]="!isFormValid() || isSaving()"
|
|
1468
|
+
[disabled]="!isFormValid() || isSaving()"
|
|
1469
|
+
/>
|
|
1517
1470
|
</div>
|
|
1518
1471
|
</form>
|
|
1519
1472
|
</p-card>
|
|
1520
1473
|
|
|
1521
1474
|
<p-toast />
|
|
1522
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type:
|
|
1475
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1523
1476
|
}
|
|
1524
1477
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LanguageFormPage, decorators: [{
|
|
1525
1478
|
type: Component,
|
|
@@ -1532,67 +1485,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1532
1485
|
<ng-template #header>
|
|
1533
1486
|
<div class="flex justify-between items-center p-4">
|
|
1534
1487
|
<h2 class="text-xl font-semibold m-0">
|
|
1535
|
-
{{
|
|
1488
|
+
{{
|
|
1489
|
+
isEditMode()
|
|
1490
|
+
? ('localization.language.edit' | translate)
|
|
1491
|
+
: ('localization.language.new' | translate)
|
|
1492
|
+
}}
|
|
1536
1493
|
</h2>
|
|
1537
1494
|
</div>
|
|
1538
1495
|
</ng-template>
|
|
1539
1496
|
|
|
1540
|
-
<form
|
|
1497
|
+
<form
|
|
1498
|
+
(ngSubmit)="onSubmit()"
|
|
1499
|
+
class="grid grid-cols-1 md:grid-cols-2 gap-4"
|
|
1500
|
+
>
|
|
1541
1501
|
<!-- Language Code -->
|
|
1542
1502
|
<div class="flex flex-col gap-2">
|
|
1543
|
-
<label for="code" class="font-medium"
|
|
1503
|
+
<label for="code" class="font-medium"
|
|
1504
|
+
>{{ 'localization.language.code' | translate }} *</label
|
|
1505
|
+
>
|
|
1544
1506
|
<input
|
|
1545
1507
|
pInputText
|
|
1546
1508
|
id="code"
|
|
1547
1509
|
[formField]="formTree.code"
|
|
1548
|
-
[placeholder]="'localization.placeholder.code' | translate"
|
|
1549
|
-
|
|
1510
|
+
[placeholder]="'localization.placeholder.code' | translate"
|
|
1511
|
+
/>
|
|
1512
|
+
<small class="text-muted-color">{{
|
|
1513
|
+
'localization.language.iso.code.hint' | translate
|
|
1514
|
+
}}</small>
|
|
1550
1515
|
</div>
|
|
1551
1516
|
|
|
1552
1517
|
<!-- Language Name -->
|
|
1553
1518
|
<div class="flex flex-col gap-2">
|
|
1554
|
-
<label for="name" class="font-medium"
|
|
1519
|
+
<label for="name" class="font-medium"
|
|
1520
|
+
>{{ 'localization.language.name' | translate }} *</label
|
|
1521
|
+
>
|
|
1555
1522
|
<input
|
|
1556
1523
|
pInputText
|
|
1557
1524
|
id="name"
|
|
1558
1525
|
[formField]="formTree.name"
|
|
1559
|
-
[placeholder]="'localization.placeholder.name' | translate"
|
|
1526
|
+
[placeholder]="'localization.placeholder.name' | translate"
|
|
1527
|
+
/>
|
|
1560
1528
|
</div>
|
|
1561
1529
|
|
|
1562
1530
|
<!-- Native Name -->
|
|
1563
1531
|
<div class="flex flex-col gap-2">
|
|
1564
|
-
<label for="nativeName" class="font-medium">{{
|
|
1532
|
+
<label for="nativeName" class="font-medium">{{
|
|
1533
|
+
'localization.language.native.name' | translate
|
|
1534
|
+
}}</label>
|
|
1565
1535
|
<input
|
|
1566
1536
|
pInputText
|
|
1567
1537
|
id="nativeName"
|
|
1568
1538
|
[formField]="formTree.nativeName"
|
|
1569
|
-
[placeholder]="'localization.placeholder.native.name' | translate"
|
|
1570
|
-
|
|
1539
|
+
[placeholder]="'localization.placeholder.native.name' | translate"
|
|
1540
|
+
/>
|
|
1541
|
+
<small class="text-muted-color">{{
|
|
1542
|
+
'localization.language.native.name.hint' | translate
|
|
1543
|
+
}}</small>
|
|
1571
1544
|
</div>
|
|
1572
1545
|
|
|
1573
1546
|
<!-- Text Direction -->
|
|
1574
1547
|
<div class="flex flex-col gap-2">
|
|
1575
|
-
<label for="direction" class="font-medium"
|
|
1548
|
+
<label for="direction" class="font-medium"
|
|
1549
|
+
>{{ 'localization.language.direction' | translate }} *</label
|
|
1550
|
+
>
|
|
1576
1551
|
<p-select
|
|
1577
1552
|
id="direction"
|
|
1578
1553
|
[ngModel]="formModel().direction"
|
|
1579
1554
|
(ngModelChange)="updateDirection($event)"
|
|
1580
|
-
[ngModelOptions]="{standalone: true}"
|
|
1555
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1581
1556
|
[options]="directionOptions()"
|
|
1582
1557
|
optionLabel="label"
|
|
1583
1558
|
optionValue="value"
|
|
1584
|
-
class="w-full"
|
|
1559
|
+
class="w-full"
|
|
1560
|
+
/>
|
|
1585
1561
|
</div>
|
|
1586
1562
|
|
|
1587
1563
|
<!-- Display Order -->
|
|
1588
1564
|
<div class="flex flex-col gap-2">
|
|
1589
|
-
<label for="serial" class="font-medium">{{
|
|
1565
|
+
<label for="serial" class="font-medium">{{
|
|
1566
|
+
'localization.language.display.order' | translate
|
|
1567
|
+
}}</label>
|
|
1590
1568
|
<input
|
|
1591
1569
|
pInputText
|
|
1592
1570
|
id="serial"
|
|
1593
1571
|
type="number"
|
|
1594
1572
|
[formField]="formTree.serial"
|
|
1595
|
-
[placeholder]="'shared.display.order.placeholder' | translate"
|
|
1573
|
+
[placeholder]="'shared.display.order.placeholder' | translate"
|
|
1574
|
+
/>
|
|
1596
1575
|
</div>
|
|
1597
1576
|
|
|
1598
1577
|
<!-- Empty cell for alignment -->
|
|
@@ -1616,12 +1595,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1616
1595
|
[label]="'shared.cancel' | translate"
|
|
1617
1596
|
severity="secondary"
|
|
1618
1597
|
[outlined]="true"
|
|
1619
|
-
(onClick)="onCancel()"
|
|
1598
|
+
(onClick)="onCancel()"
|
|
1599
|
+
/>
|
|
1620
1600
|
<p-button
|
|
1621
|
-
[label]="
|
|
1601
|
+
[label]="
|
|
1602
|
+
isEditMode()
|
|
1603
|
+
? ('shared.update' | translate)
|
|
1604
|
+
: ('shared.create' | translate)
|
|
1605
|
+
"
|
|
1622
1606
|
type="submit"
|
|
1623
1607
|
[loading]="isSaving()"
|
|
1624
|
-
[disabled]="!isFormValid() || isSaving()"
|
|
1608
|
+
[disabled]="!isFormValid() || isSaving()"
|
|
1609
|
+
/>
|
|
1625
1610
|
</div>
|
|
1626
1611
|
</form>
|
|
1627
1612
|
</p-card>
|
|
@@ -1654,7 +1639,7 @@ class TranslationKeyListPage {
|
|
|
1654
1639
|
selectedModule = signal(null, ...(ngDevMode ? [{ debugName: "selectedModule" }] : []));
|
|
1655
1640
|
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
1656
1641
|
moduleOptions = computed(() => [
|
|
1657
|
-
{ label: this.translateService.
|
|
1642
|
+
{ label: this.translateService.translate('shared.all'), value: null },
|
|
1658
1643
|
...this.modules().map((m) => ({ label: m, value: m })),
|
|
1659
1644
|
], ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
1660
1645
|
filteredKeys = computed(() => {
|
|
@@ -1677,9 +1662,17 @@ class TranslationKeyListPage {
|
|
|
1677
1662
|
loadData() {
|
|
1678
1663
|
this.isLoading.set(true);
|
|
1679
1664
|
forkJoin({
|
|
1680
|
-
languages: this.languageService.getAll(
|
|
1665
|
+
languages: from(this.languageService.getAll({
|
|
1666
|
+
pagination: { currentPage: 0, pageSize: 100 },
|
|
1667
|
+
filter: {},
|
|
1668
|
+
sort: { serial: 'ASC', name: 'ASC' },
|
|
1669
|
+
})),
|
|
1681
1670
|
modules: this.translationKeyService.getModules(),
|
|
1682
|
-
keys: this.translationKeyService.getAll(
|
|
1671
|
+
keys: from(this.translationKeyService.getAll({
|
|
1672
|
+
pagination: { currentPage: 0, pageSize: 1000 },
|
|
1673
|
+
filter: {},
|
|
1674
|
+
sort: { module: 'ASC', key: 'ASC' },
|
|
1675
|
+
})),
|
|
1683
1676
|
})
|
|
1684
1677
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1685
1678
|
.subscribe({
|
|
@@ -1702,7 +1695,8 @@ class TranslationKeyListPage {
|
|
|
1702
1695
|
});
|
|
1703
1696
|
}
|
|
1704
1697
|
loadTranslationCounts() {
|
|
1705
|
-
this.translationService
|
|
1698
|
+
this.translationService
|
|
1699
|
+
.getCounts()
|
|
1706
1700
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1707
1701
|
.subscribe({
|
|
1708
1702
|
next: (response) => {
|
|
@@ -1731,15 +1725,17 @@ class TranslationKeyListPage {
|
|
|
1731
1725
|
icon: 'pi pi-exclamation-triangle',
|
|
1732
1726
|
acceptButtonStyleClass: 'p-button-danger',
|
|
1733
1727
|
accept: () => {
|
|
1734
|
-
this.translationKeyService.delete(key.id)
|
|
1728
|
+
from(this.translationKeyService.delete({ id: key.id, type: 'delete' }))
|
|
1735
1729
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1736
1730
|
.subscribe({
|
|
1737
1731
|
next: (response) => {
|
|
1738
1732
|
if (response.success) {
|
|
1739
1733
|
this.messageService.add({
|
|
1740
1734
|
severity: 'success',
|
|
1741
|
-
summary: this.translateService.
|
|
1742
|
-
detail:
|
|
1735
|
+
summary: this.translateService.translate('shared.success'),
|
|
1736
|
+
detail: response.messageKey
|
|
1737
|
+
? this.translateService.translate(response.messageKey, response.messageVariables)
|
|
1738
|
+
: (response.message ?? ''),
|
|
1743
1739
|
});
|
|
1744
1740
|
this.loadData();
|
|
1745
1741
|
}
|
|
@@ -1751,29 +1747,34 @@ class TranslationKeyListPage {
|
|
|
1751
1747
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyListPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1752
1748
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: TranslationKeyListPage, isStandalone: true, selector: "lib-translation-key-list-page", providers: [ConfirmationService, MessageService], ngImport: i0, template: `
|
|
1753
1749
|
<div class="card">
|
|
1754
|
-
<div
|
|
1750
|
+
<div
|
|
1751
|
+
class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
|
|
1752
|
+
>
|
|
1755
1753
|
<div>
|
|
1756
|
-
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1757
|
-
|
|
1754
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1755
|
+
{{ 'localization.key.title' | translate }}
|
|
1756
|
+
</h3>
|
|
1757
|
+
<p class="text-sm text-muted-color mt-1">
|
|
1758
|
+
{{ 'localization.key.subtitle' | translate }}
|
|
1759
|
+
</p>
|
|
1758
1760
|
</div>
|
|
1759
1761
|
<div class="flex gap-2">
|
|
1760
1762
|
<p-button
|
|
1761
1763
|
*hasPermission="TRANSLATION_KEY_PERMISSIONS.CREATE"
|
|
1762
|
-
[label]="'localization.key.
|
|
1764
|
+
[label]="'localization.key.new' | translate"
|
|
1763
1765
|
icon="pi pi-plus"
|
|
1764
1766
|
(onClick)="onCreate()"
|
|
1765
1767
|
/>
|
|
1766
1768
|
</div>
|
|
1767
1769
|
</div>
|
|
1768
1770
|
|
|
1769
|
-
<!-- Filters -->
|
|
1770
1771
|
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
1771
1772
|
<div class="flex-1">
|
|
1772
1773
|
<p-select
|
|
1773
1774
|
[options]="moduleOptions()"
|
|
1774
1775
|
[ngModel]="selectedModule()"
|
|
1775
1776
|
(ngModelChange)="onModuleChange($event)"
|
|
1776
|
-
[ngModelOptions]="{standalone: true}"
|
|
1777
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1777
1778
|
optionLabel="label"
|
|
1778
1779
|
optionValue="value"
|
|
1779
1780
|
[placeholder]="'localization.key.filter.module' | translate"
|
|
@@ -1788,7 +1789,7 @@ class TranslationKeyListPage {
|
|
|
1788
1789
|
pInputText
|
|
1789
1790
|
[ngModel]="searchTerm()"
|
|
1790
1791
|
(ngModelChange)="searchTerm.set($event)"
|
|
1791
|
-
[ngModelOptions]="{standalone: true}"
|
|
1792
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1792
1793
|
[placeholder]="'shared.search' | translate"
|
|
1793
1794
|
class="w-full"
|
|
1794
1795
|
/>
|
|
@@ -1803,18 +1804,28 @@ class TranslationKeyListPage {
|
|
|
1803
1804
|
[paginator]="true"
|
|
1804
1805
|
[rows]="15"
|
|
1805
1806
|
[rowsPerPageOptions]="[10, 15, 25, 50]"
|
|
1806
|
-
|
|
1807
|
+
class="p-datatable-sm"
|
|
1807
1808
|
>
|
|
1808
1809
|
<ng-template #header>
|
|
1809
1810
|
<tr>
|
|
1810
|
-
<th style="width: 15%">
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
<th style="width:
|
|
1811
|
+
<th style="width: 15%">
|
|
1812
|
+
{{ 'localization.key.module' | translate }}
|
|
1813
|
+
</th>
|
|
1814
|
+
<th style="width: 25%">
|
|
1815
|
+
{{ 'localization.key.name' | translate }}
|
|
1816
|
+
</th>
|
|
1817
|
+
<th style="width: 35%">
|
|
1818
|
+
{{ 'localization.key.default.message' | translate }}
|
|
1819
|
+
</th>
|
|
1820
|
+
<th style="width: 10%">
|
|
1821
|
+
{{ 'localization.key.translations' | translate }}
|
|
1822
|
+
</th>
|
|
1814
1823
|
<th style="width: 15%">{{ 'shared.actions' | translate }}</th>
|
|
1815
1824
|
</tr>
|
|
1816
1825
|
</ng-template>
|
|
1817
1826
|
<ng-template #body let-key>
|
|
1827
|
+
@let translationCount = getTranslationCount(key.id);
|
|
1828
|
+
@let languageCount = languages().length;
|
|
1818
1829
|
<tr>
|
|
1819
1830
|
<td>
|
|
1820
1831
|
<p-tag [value]="key.module" severity="secondary" />
|
|
@@ -1827,8 +1838,13 @@ class TranslationKeyListPage {
|
|
|
1827
1838
|
</td>
|
|
1828
1839
|
<td>{{ key.defaultMessage }}</td>
|
|
1829
1840
|
<td class="text-center">
|
|
1830
|
-
<span
|
|
1831
|
-
|
|
1841
|
+
<span
|
|
1842
|
+
class="text-sm"
|
|
1843
|
+
[class.text-green-500]="translationCount === languageCount"
|
|
1844
|
+
[class.text-orange-500]="translationCount < languageCount && translationCount > 0"
|
|
1845
|
+
[class.text-muted-color]="translationCount === 0"
|
|
1846
|
+
>
|
|
1847
|
+
{{ translationCount }}/{{ languageCount }}
|
|
1832
1848
|
</span>
|
|
1833
1849
|
</td>
|
|
1834
1850
|
<td>
|
|
@@ -1867,39 +1883,50 @@ class TranslationKeyListPage {
|
|
|
1867
1883
|
|
|
1868
1884
|
<p-confirmDialog />
|
|
1869
1885
|
<p-toast />
|
|
1870
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: i4$2.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i5$
|
|
1886
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2$1.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: i4$2.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i5$2.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i6.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
1871
1887
|
}
|
|
1872
1888
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyListPage, decorators: [{
|
|
1873
1889
|
type: Component,
|
|
1874
1890
|
args: [{
|
|
1875
1891
|
selector: 'lib-translation-key-list-page',
|
|
1876
|
-
imports: [
|
|
1892
|
+
imports: [
|
|
1893
|
+
AngularModule,
|
|
1894
|
+
PrimeModule,
|
|
1895
|
+
FormsModule,
|
|
1896
|
+
HasPermissionDirective,
|
|
1897
|
+
TranslatePipe,
|
|
1898
|
+
],
|
|
1877
1899
|
providers: [ConfirmationService, MessageService],
|
|
1878
1900
|
template: `
|
|
1879
1901
|
<div class="card">
|
|
1880
|
-
<div
|
|
1902
|
+
<div
|
|
1903
|
+
class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4"
|
|
1904
|
+
>
|
|
1881
1905
|
<div>
|
|
1882
|
-
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1883
|
-
|
|
1906
|
+
<h3 class="text-lg sm:text-xl font-semibold m-0">
|
|
1907
|
+
{{ 'localization.key.title' | translate }}
|
|
1908
|
+
</h3>
|
|
1909
|
+
<p class="text-sm text-muted-color mt-1">
|
|
1910
|
+
{{ 'localization.key.subtitle' | translate }}
|
|
1911
|
+
</p>
|
|
1884
1912
|
</div>
|
|
1885
1913
|
<div class="flex gap-2">
|
|
1886
1914
|
<p-button
|
|
1887
1915
|
*hasPermission="TRANSLATION_KEY_PERMISSIONS.CREATE"
|
|
1888
|
-
[label]="'localization.key.
|
|
1916
|
+
[label]="'localization.key.new' | translate"
|
|
1889
1917
|
icon="pi pi-plus"
|
|
1890
1918
|
(onClick)="onCreate()"
|
|
1891
1919
|
/>
|
|
1892
1920
|
</div>
|
|
1893
1921
|
</div>
|
|
1894
1922
|
|
|
1895
|
-
<!-- Filters -->
|
|
1896
1923
|
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
1897
1924
|
<div class="flex-1">
|
|
1898
1925
|
<p-select
|
|
1899
1926
|
[options]="moduleOptions()"
|
|
1900
1927
|
[ngModel]="selectedModule()"
|
|
1901
1928
|
(ngModelChange)="onModuleChange($event)"
|
|
1902
|
-
[ngModelOptions]="{standalone: true}"
|
|
1929
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1903
1930
|
optionLabel="label"
|
|
1904
1931
|
optionValue="value"
|
|
1905
1932
|
[placeholder]="'localization.key.filter.module' | translate"
|
|
@@ -1914,7 +1941,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1914
1941
|
pInputText
|
|
1915
1942
|
[ngModel]="searchTerm()"
|
|
1916
1943
|
(ngModelChange)="searchTerm.set($event)"
|
|
1917
|
-
[ngModelOptions]="{standalone: true}"
|
|
1944
|
+
[ngModelOptions]="{ standalone: true }"
|
|
1918
1945
|
[placeholder]="'shared.search' | translate"
|
|
1919
1946
|
class="w-full"
|
|
1920
1947
|
/>
|
|
@@ -1929,18 +1956,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1929
1956
|
[paginator]="true"
|
|
1930
1957
|
[rows]="15"
|
|
1931
1958
|
[rowsPerPageOptions]="[10, 15, 25, 50]"
|
|
1932
|
-
|
|
1959
|
+
class="p-datatable-sm"
|
|
1933
1960
|
>
|
|
1934
1961
|
<ng-template #header>
|
|
1935
1962
|
<tr>
|
|
1936
|
-
<th style="width: 15%">
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
<th style="width:
|
|
1963
|
+
<th style="width: 15%">
|
|
1964
|
+
{{ 'localization.key.module' | translate }}
|
|
1965
|
+
</th>
|
|
1966
|
+
<th style="width: 25%">
|
|
1967
|
+
{{ 'localization.key.name' | translate }}
|
|
1968
|
+
</th>
|
|
1969
|
+
<th style="width: 35%">
|
|
1970
|
+
{{ 'localization.key.default.message' | translate }}
|
|
1971
|
+
</th>
|
|
1972
|
+
<th style="width: 10%">
|
|
1973
|
+
{{ 'localization.key.translations' | translate }}
|
|
1974
|
+
</th>
|
|
1940
1975
|
<th style="width: 15%">{{ 'shared.actions' | translate }}</th>
|
|
1941
1976
|
</tr>
|
|
1942
1977
|
</ng-template>
|
|
1943
1978
|
<ng-template #body let-key>
|
|
1979
|
+
@let translationCount = getTranslationCount(key.id);
|
|
1980
|
+
@let languageCount = languages().length;
|
|
1944
1981
|
<tr>
|
|
1945
1982
|
<td>
|
|
1946
1983
|
<p-tag [value]="key.module" severity="secondary" />
|
|
@@ -1953,8 +1990,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1953
1990
|
</td>
|
|
1954
1991
|
<td>{{ key.defaultMessage }}</td>
|
|
1955
1992
|
<td class="text-center">
|
|
1956
|
-
<span
|
|
1957
|
-
|
|
1993
|
+
<span
|
|
1994
|
+
class="text-sm"
|
|
1995
|
+
[class.text-green-500]="translationCount === languageCount"
|
|
1996
|
+
[class.text-orange-500]="translationCount < languageCount && translationCount > 0"
|
|
1997
|
+
[class.text-muted-color]="translationCount === 0"
|
|
1998
|
+
>
|
|
1999
|
+
{{ translationCount }}/{{ languageCount }}
|
|
1958
2000
|
</span>
|
|
1959
2001
|
</td>
|
|
1960
2002
|
<td>
|
|
@@ -2009,7 +2051,9 @@ class TranslationKeyFormPage {
|
|
|
2009
2051
|
translationKeyService = inject(TranslationKeyApiService);
|
|
2010
2052
|
translationService = inject(TranslationApiService);
|
|
2011
2053
|
messageService = inject(MessageService);
|
|
2012
|
-
translateAdapter = inject(TRANSLATE_ADAPTER, {
|
|
2054
|
+
translateAdapter = inject(TRANSLATE_ADAPTER, {
|
|
2055
|
+
optional: true,
|
|
2056
|
+
});
|
|
2013
2057
|
destroyRef = inject(DestroyRef);
|
|
2014
2058
|
routeParams = toSignal(this.route.paramMap);
|
|
2015
2059
|
loadTriggered = false;
|
|
@@ -2020,8 +2064,8 @@ class TranslationKeyFormPage {
|
|
|
2020
2064
|
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
2021
2065
|
modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
|
|
2022
2066
|
translations = signal([], ...(ngDevMode ? [{ debugName: "translations" }] : []));
|
|
2023
|
-
translate(key) {
|
|
2024
|
-
return this.translateAdapter?.translate(key) ?? key;
|
|
2067
|
+
translate(key, vars) {
|
|
2068
|
+
return this.translateAdapter?.translate(key, vars) ?? key;
|
|
2025
2069
|
}
|
|
2026
2070
|
moduleOptions = computed(() => this.modules().map((m) => ({ label: m, value: m })), ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
2027
2071
|
formModel = signal({
|
|
@@ -2032,12 +2076,18 @@ class TranslationKeyFormPage {
|
|
|
2032
2076
|
variables: '',
|
|
2033
2077
|
}, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
|
|
2034
2078
|
formTree = form(this.formModel, (f) => {
|
|
2035
|
-
required(f.key, {
|
|
2036
|
-
|
|
2079
|
+
required(f.key, {
|
|
2080
|
+
message: this.translate('localization.validation.key.required'),
|
|
2081
|
+
});
|
|
2082
|
+
required(f.defaultMessage, {
|
|
2083
|
+
message: this.translate('localization.validation.default.message.required'),
|
|
2084
|
+
});
|
|
2037
2085
|
});
|
|
2038
2086
|
isFormValid = computed(() => {
|
|
2039
2087
|
const model = this.formModel();
|
|
2040
|
-
return model.key.trim().length > 0 &&
|
|
2088
|
+
return (model.key.trim().length > 0 &&
|
|
2089
|
+
model.module.trim().length > 0 &&
|
|
2090
|
+
model.defaultMessage.trim().length > 0);
|
|
2041
2091
|
}, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
|
|
2042
2092
|
constructor() {
|
|
2043
2093
|
effect(() => {
|
|
@@ -2057,7 +2107,11 @@ class TranslationKeyFormPage {
|
|
|
2057
2107
|
loadInitialData() {
|
|
2058
2108
|
this.isLoadingLanguages.set(true);
|
|
2059
2109
|
forkJoin({
|
|
2060
|
-
languages: this.languageService.getAll(
|
|
2110
|
+
languages: from(this.languageService.getAll({
|
|
2111
|
+
pagination: { currentPage: 0, pageSize: 100 },
|
|
2112
|
+
filter: {},
|
|
2113
|
+
sort: { serial: 'ASC', name: 'ASC' },
|
|
2114
|
+
})),
|
|
2061
2115
|
modules: this.translationKeyService.getModules(),
|
|
2062
2116
|
})
|
|
2063
2117
|
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isLoadingLanguages.set(false)))
|
|
@@ -2084,20 +2138,20 @@ class TranslationKeyFormPage {
|
|
|
2084
2138
|
this.formModel.update((m) => ({ ...m, module: value ?? '' }));
|
|
2085
2139
|
}
|
|
2086
2140
|
getTranslationValue(languageId) {
|
|
2087
|
-
return this.translations().find((t) => t.languageId === languageId)?.value ?? '';
|
|
2141
|
+
return (this.translations().find((t) => t.languageId === languageId)?.value ?? '');
|
|
2088
2142
|
}
|
|
2089
2143
|
setTranslationValue(languageId, value) {
|
|
2090
2144
|
this.translations.update((list) => {
|
|
2091
2145
|
const existing = list.find((t) => t.languageId === languageId);
|
|
2092
2146
|
if (existing) {
|
|
2093
|
-
return list.map((t) =>
|
|
2147
|
+
return list.map((t) => t.languageId === languageId ? { ...t, value } : t);
|
|
2094
2148
|
}
|
|
2095
2149
|
return [...list, { languageId, value }];
|
|
2096
2150
|
});
|
|
2097
2151
|
}
|
|
2098
2152
|
loadTranslationKey(id) {
|
|
2099
2153
|
this.isSaving.set(true);
|
|
2100
|
-
this.translationKeyService.
|
|
2154
|
+
from(this.translationKeyService.findById(id))
|
|
2101
2155
|
.pipe(takeUntilDestroyed(this.destroyRef), finalize(() => this.isSaving.set(false)))
|
|
2102
2156
|
.subscribe({
|
|
2103
2157
|
next: (response) => {
|
|
@@ -2111,7 +2165,8 @@ class TranslationKeyFormPage {
|
|
|
2111
2165
|
});
|
|
2112
2166
|
}
|
|
2113
2167
|
loadExistingTranslations(keyId) {
|
|
2114
|
-
this.translationService
|
|
2168
|
+
this.translationService
|
|
2169
|
+
.getByKeyId(keyId)
|
|
2115
2170
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2116
2171
|
.subscribe({
|
|
2117
2172
|
next: (response) => {
|
|
@@ -2125,7 +2180,11 @@ class TranslationKeyFormPage {
|
|
|
2125
2180
|
existing.translationId = t.id;
|
|
2126
2181
|
}
|
|
2127
2182
|
else {
|
|
2128
|
-
updated.push({
|
|
2183
|
+
updated.push({
|
|
2184
|
+
languageId: t.languageId,
|
|
2185
|
+
value: t.value,
|
|
2186
|
+
translationId: t.id,
|
|
2187
|
+
});
|
|
2129
2188
|
}
|
|
2130
2189
|
});
|
|
2131
2190
|
return updated;
|
|
@@ -2167,12 +2226,12 @@ class TranslationKeyFormPage {
|
|
|
2167
2226
|
description: model.description || undefined,
|
|
2168
2227
|
variables: variables.length > 0 ? variables : undefined,
|
|
2169
2228
|
};
|
|
2170
|
-
this.translationKeyService.
|
|
2229
|
+
from(this.translationKeyService.insert(createDto))
|
|
2171
2230
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2172
2231
|
.subscribe({
|
|
2173
2232
|
next: (response) => {
|
|
2174
2233
|
if (response.success && response.data) {
|
|
2175
|
-
this.saveTranslations(response.data.id);
|
|
2234
|
+
this.saveTranslations(response.data.id, response.messageKey, response.messageVariables);
|
|
2176
2235
|
}
|
|
2177
2236
|
else {
|
|
2178
2237
|
this.isSaving.set(false);
|
|
@@ -2190,12 +2249,12 @@ class TranslationKeyFormPage {
|
|
|
2190
2249
|
description: model.description || undefined,
|
|
2191
2250
|
variables: variables.length > 0 ? variables : undefined,
|
|
2192
2251
|
};
|
|
2193
|
-
this.translationKeyService.update(updateDto)
|
|
2252
|
+
from(this.translationKeyService.update(updateDto))
|
|
2194
2253
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2195
2254
|
.subscribe({
|
|
2196
2255
|
next: (response) => {
|
|
2197
2256
|
if (response.success) {
|
|
2198
|
-
this.saveTranslations(this.existingKey().id);
|
|
2257
|
+
this.saveTranslations(this.existingKey().id, response.messageKey, response.messageVariables);
|
|
2199
2258
|
}
|
|
2200
2259
|
else {
|
|
2201
2260
|
this.isSaving.set(false);
|
|
@@ -2204,7 +2263,7 @@ class TranslationKeyFormPage {
|
|
|
2204
2263
|
error: () => this.isSaving.set(false),
|
|
2205
2264
|
});
|
|
2206
2265
|
}
|
|
2207
|
-
saveTranslations(keyId) {
|
|
2266
|
+
saveTranslations(keyId, messageKey, messageVariables) {
|
|
2208
2267
|
const translationsToSave = this.translations()
|
|
2209
2268
|
.filter((t) => t.value?.trim())
|
|
2210
2269
|
.map((t) => ({
|
|
@@ -2215,21 +2274,22 @@ class TranslationKeyFormPage {
|
|
|
2215
2274
|
isVerified: false,
|
|
2216
2275
|
}));
|
|
2217
2276
|
if (translationsToSave.length === 0) {
|
|
2218
|
-
this.onSaveSuccess();
|
|
2277
|
+
this.onSaveSuccess(messageKey, messageVariables);
|
|
2219
2278
|
return;
|
|
2220
2279
|
}
|
|
2221
|
-
this.translationService
|
|
2280
|
+
this.translationService
|
|
2281
|
+
.bulkUpdate(translationsToSave)
|
|
2222
2282
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2223
2283
|
.subscribe({
|
|
2224
|
-
next: () => this.onSaveSuccess(),
|
|
2225
|
-
error: () => this.onSaveSuccess(),
|
|
2284
|
+
next: () => this.onSaveSuccess(messageKey, messageVariables),
|
|
2285
|
+
error: () => this.onSaveSuccess(messageKey, messageVariables),
|
|
2226
2286
|
});
|
|
2227
2287
|
}
|
|
2228
|
-
onSaveSuccess() {
|
|
2288
|
+
onSaveSuccess(messageKey, messageVariables) {
|
|
2229
2289
|
this.messageService.add({
|
|
2230
2290
|
severity: 'success',
|
|
2231
2291
|
summary: this.translate('shared.success'),
|
|
2232
|
-
detail: this.translate(
|
|
2292
|
+
detail: messageKey ? this.translate(messageKey, messageVariables) : '',
|
|
2233
2293
|
});
|
|
2234
2294
|
this.isSaving.set(false);
|
|
2235
2295
|
this.router.navigate(['/localization/keys']);
|
|
@@ -2243,7 +2303,11 @@ class TranslationKeyFormPage {
|
|
|
2243
2303
|
<ng-template #header>
|
|
2244
2304
|
<div class="flex justify-between items-center p-4">
|
|
2245
2305
|
<h2 class="text-xl font-semibold m-0">
|
|
2246
|
-
{{
|
|
2306
|
+
{{
|
|
2307
|
+
isEditMode()
|
|
2308
|
+
? ('localization.key.edit' | translate)
|
|
2309
|
+
: ('localization.key.new' | translate)
|
|
2310
|
+
}}
|
|
2247
2311
|
</h2>
|
|
2248
2312
|
</div>
|
|
2249
2313
|
</ng-template>
|
|
@@ -2251,71 +2315,98 @@ class TranslationKeyFormPage {
|
|
|
2251
2315
|
<form (ngSubmit)="onSubmit()" class="flex flex-col gap-6">
|
|
2252
2316
|
<!-- Key Info Section -->
|
|
2253
2317
|
<div class="p-4 surface-ground rounded-lg">
|
|
2254
|
-
<h4 class="font-semibold mt-0 mb-4">
|
|
2318
|
+
<h4 class="font-semibold mt-0 mb-4">
|
|
2319
|
+
{{ 'localization.key.about' | translate }}
|
|
2320
|
+
</h4>
|
|
2255
2321
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
2256
2322
|
<!-- Key Name -->
|
|
2257
2323
|
<div class="flex flex-col gap-2">
|
|
2258
|
-
<label for="key" class="font-medium"
|
|
2324
|
+
<label for="key" class="font-medium"
|
|
2325
|
+
>{{ 'localization.key.name' | translate }} *</label
|
|
2326
|
+
>
|
|
2259
2327
|
<input
|
|
2260
2328
|
pInputText
|
|
2261
2329
|
id="key"
|
|
2262
2330
|
[formField]="formTree.key"
|
|
2263
|
-
[placeholder]="'localization.placeholder.key.name' | translate"
|
|
2331
|
+
[placeholder]="'localization.placeholder.key.name' | translate"
|
|
2332
|
+
/>
|
|
2264
2333
|
</div>
|
|
2265
2334
|
|
|
2266
2335
|
<!-- Module -->
|
|
2267
2336
|
<div class="flex flex-col gap-2">
|
|
2268
|
-
<label for="module" class="font-medium"
|
|
2337
|
+
<label for="module" class="font-medium"
|
|
2338
|
+
>{{ 'localization.key.module' | translate }} *</label
|
|
2339
|
+
>
|
|
2269
2340
|
<p-select
|
|
2270
2341
|
id="module"
|
|
2271
2342
|
[ngModel]="formModel().module"
|
|
2272
2343
|
(ngModelChange)="updateModule($event)"
|
|
2273
|
-
[ngModelOptions]="{standalone: true}"
|
|
2344
|
+
[ngModelOptions]="{ standalone: true }"
|
|
2274
2345
|
[options]="moduleOptions()"
|
|
2275
2346
|
optionLabel="label"
|
|
2276
2347
|
optionValue="value"
|
|
2277
2348
|
[editable]="true"
|
|
2278
2349
|
[placeholder]="'localization.key.select.module' | translate"
|
|
2279
|
-
class="w-full"
|
|
2350
|
+
class="w-full"
|
|
2351
|
+
/>
|
|
2280
2352
|
</div>
|
|
2281
2353
|
|
|
2282
2354
|
<!-- Default Message -->
|
|
2283
2355
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2284
|
-
<label for="defaultMessage" class="font-medium"
|
|
2356
|
+
<label for="defaultMessage" class="font-medium"
|
|
2357
|
+
>{{ 'localization.key.default.message' | translate }} *</label
|
|
2358
|
+
>
|
|
2285
2359
|
<textarea
|
|
2286
2360
|
pInputTextarea
|
|
2287
2361
|
id="defaultMessage"
|
|
2288
2362
|
[formField]="formTree.defaultMessage"
|
|
2289
2363
|
[rows]="2"
|
|
2290
|
-
[placeholder]="
|
|
2364
|
+
[placeholder]="
|
|
2365
|
+
'localization.placeholder.default.message' | translate
|
|
2366
|
+
"
|
|
2367
|
+
></textarea>
|
|
2291
2368
|
</div>
|
|
2292
2369
|
|
|
2293
2370
|
<!-- Description -->
|
|
2294
2371
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2295
|
-
<label for="description" class="font-medium">{{
|
|
2372
|
+
<label for="description" class="font-medium">{{
|
|
2373
|
+
'localization.key.description' | translate
|
|
2374
|
+
}}</label>
|
|
2296
2375
|
<input
|
|
2297
2376
|
pInputText
|
|
2298
2377
|
id="description"
|
|
2299
2378
|
[formField]="formTree.description"
|
|
2300
|
-
[placeholder]="
|
|
2379
|
+
[placeholder]="
|
|
2380
|
+
'localization.placeholder.key.description' | translate
|
|
2381
|
+
"
|
|
2382
|
+
/>
|
|
2301
2383
|
</div>
|
|
2302
2384
|
|
|
2303
2385
|
<!-- Variables -->
|
|
2304
2386
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2305
|
-
<label for="variables" class="font-medium">{{
|
|
2387
|
+
<label for="variables" class="font-medium">{{
|
|
2388
|
+
'localization.key.variables' | translate
|
|
2389
|
+
}}</label>
|
|
2306
2390
|
<input
|
|
2307
2391
|
pInputText
|
|
2308
2392
|
id="variables"
|
|
2309
2393
|
[formField]="formTree.variables"
|
|
2310
|
-
[placeholder]="
|
|
2311
|
-
|
|
2394
|
+
[placeholder]="
|
|
2395
|
+
'localization.key.variables.placeholder' | translate
|
|
2396
|
+
"
|
|
2397
|
+
/>
|
|
2398
|
+
<small class="text-muted-color">{{
|
|
2399
|
+
'localization.key.variables.hint' | translate
|
|
2400
|
+
}}</small>
|
|
2312
2401
|
</div>
|
|
2313
2402
|
</div>
|
|
2314
2403
|
</div>
|
|
2315
2404
|
|
|
2316
2405
|
<!-- Translations Section -->
|
|
2317
2406
|
<div class="p-4 surface-ground rounded-lg">
|
|
2318
|
-
<h4 class="font-semibold mt-0 mb-4">
|
|
2407
|
+
<h4 class="font-semibold mt-0 mb-4">
|
|
2408
|
+
{{ 'localization.key.translations.section' | translate }}
|
|
2409
|
+
</h4>
|
|
2319
2410
|
@if (isLoadingLanguages()) {
|
|
2320
2411
|
<div class="flex justify-center py-4">
|
|
2321
2412
|
<p-progressSpinner strokeWidth="4" />
|
|
@@ -2332,18 +2423,28 @@ class TranslationKeyFormPage {
|
|
|
2332
2423
|
<label class="font-medium">
|
|
2333
2424
|
{{ lang.name }}
|
|
2334
2425
|
@if (lang.nativeName && lang.nativeName !== lang.name) {
|
|
2335
|
-
<span class="text-muted-color"
|
|
2426
|
+
<span class="text-muted-color"
|
|
2427
|
+
>({{ lang.nativeName }})</span
|
|
2428
|
+
>
|
|
2336
2429
|
}
|
|
2337
2430
|
</label>
|
|
2338
|
-
<p-tag
|
|
2431
|
+
<p-tag
|
|
2432
|
+
[value]="lang.code"
|
|
2433
|
+
severity="secondary"
|
|
2434
|
+
class="uppercase"
|
|
2435
|
+
/>
|
|
2339
2436
|
</div>
|
|
2340
2437
|
<textarea
|
|
2341
2438
|
pInputTextarea
|
|
2342
2439
|
[ngModel]="getTranslationValue(lang.id)"
|
|
2343
2440
|
(ngModelChange)="setTranslationValue(lang.id, $event)"
|
|
2344
|
-
[ngModelOptions]="{standalone: true}"
|
|
2441
|
+
[ngModelOptions]="{ standalone: true }"
|
|
2345
2442
|
[rows]="2"
|
|
2346
|
-
[placeholder]="
|
|
2443
|
+
[placeholder]="
|
|
2444
|
+
formModel().defaultMessage ||
|
|
2445
|
+
('localization.key.enter.translation' | translate)
|
|
2446
|
+
"
|
|
2447
|
+
></textarea>
|
|
2347
2448
|
</div>
|
|
2348
2449
|
}
|
|
2349
2450
|
</div>
|
|
@@ -2356,18 +2457,24 @@ class TranslationKeyFormPage {
|
|
|
2356
2457
|
[label]="'shared.cancel' | translate"
|
|
2357
2458
|
severity="secondary"
|
|
2358
2459
|
[outlined]="true"
|
|
2359
|
-
(onClick)="onCancel()"
|
|
2460
|
+
(onClick)="onCancel()"
|
|
2461
|
+
/>
|
|
2360
2462
|
<p-button
|
|
2361
|
-
[label]="
|
|
2463
|
+
[label]="
|
|
2464
|
+
isEditMode()
|
|
2465
|
+
? ('shared.update' | translate)
|
|
2466
|
+
: ('shared.create' | translate)
|
|
2467
|
+
"
|
|
2362
2468
|
type="submit"
|
|
2363
2469
|
[loading]="isSaving()"
|
|
2364
|
-
[disabled]="!isFormValid() || isSaving()"
|
|
2470
|
+
[disabled]="!isFormValid() || isSaving()"
|
|
2471
|
+
/>
|
|
2365
2472
|
</div>
|
|
2366
2473
|
</form>
|
|
2367
2474
|
</p-card>
|
|
2368
2475
|
|
|
2369
2476
|
<p-toast />
|
|
2370
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: i7.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type:
|
|
2477
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: i7.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type: i5.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i9.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2371
2478
|
}
|
|
2372
2479
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationKeyFormPage, decorators: [{
|
|
2373
2480
|
type: Component,
|
|
@@ -2380,7 +2487,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
2380
2487
|
<ng-template #header>
|
|
2381
2488
|
<div class="flex justify-between items-center p-4">
|
|
2382
2489
|
<h2 class="text-xl font-semibold m-0">
|
|
2383
|
-
{{
|
|
2490
|
+
{{
|
|
2491
|
+
isEditMode()
|
|
2492
|
+
? ('localization.key.edit' | translate)
|
|
2493
|
+
: ('localization.key.new' | translate)
|
|
2494
|
+
}}
|
|
2384
2495
|
</h2>
|
|
2385
2496
|
</div>
|
|
2386
2497
|
</ng-template>
|
|
@@ -2388,71 +2499,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
2388
2499
|
<form (ngSubmit)="onSubmit()" class="flex flex-col gap-6">
|
|
2389
2500
|
<!-- Key Info Section -->
|
|
2390
2501
|
<div class="p-4 surface-ground rounded-lg">
|
|
2391
|
-
<h4 class="font-semibold mt-0 mb-4">
|
|
2502
|
+
<h4 class="font-semibold mt-0 mb-4">
|
|
2503
|
+
{{ 'localization.key.about' | translate }}
|
|
2504
|
+
</h4>
|
|
2392
2505
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
2393
2506
|
<!-- Key Name -->
|
|
2394
2507
|
<div class="flex flex-col gap-2">
|
|
2395
|
-
<label for="key" class="font-medium"
|
|
2508
|
+
<label for="key" class="font-medium"
|
|
2509
|
+
>{{ 'localization.key.name' | translate }} *</label
|
|
2510
|
+
>
|
|
2396
2511
|
<input
|
|
2397
2512
|
pInputText
|
|
2398
2513
|
id="key"
|
|
2399
2514
|
[formField]="formTree.key"
|
|
2400
|
-
[placeholder]="'localization.placeholder.key.name' | translate"
|
|
2515
|
+
[placeholder]="'localization.placeholder.key.name' | translate"
|
|
2516
|
+
/>
|
|
2401
2517
|
</div>
|
|
2402
2518
|
|
|
2403
2519
|
<!-- Module -->
|
|
2404
2520
|
<div class="flex flex-col gap-2">
|
|
2405
|
-
<label for="module" class="font-medium"
|
|
2521
|
+
<label for="module" class="font-medium"
|
|
2522
|
+
>{{ 'localization.key.module' | translate }} *</label
|
|
2523
|
+
>
|
|
2406
2524
|
<p-select
|
|
2407
2525
|
id="module"
|
|
2408
2526
|
[ngModel]="formModel().module"
|
|
2409
2527
|
(ngModelChange)="updateModule($event)"
|
|
2410
|
-
[ngModelOptions]="{standalone: true}"
|
|
2528
|
+
[ngModelOptions]="{ standalone: true }"
|
|
2411
2529
|
[options]="moduleOptions()"
|
|
2412
2530
|
optionLabel="label"
|
|
2413
2531
|
optionValue="value"
|
|
2414
2532
|
[editable]="true"
|
|
2415
2533
|
[placeholder]="'localization.key.select.module' | translate"
|
|
2416
|
-
class="w-full"
|
|
2534
|
+
class="w-full"
|
|
2535
|
+
/>
|
|
2417
2536
|
</div>
|
|
2418
2537
|
|
|
2419
2538
|
<!-- Default Message -->
|
|
2420
2539
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2421
|
-
<label for="defaultMessage" class="font-medium"
|
|
2540
|
+
<label for="defaultMessage" class="font-medium"
|
|
2541
|
+
>{{ 'localization.key.default.message' | translate }} *</label
|
|
2542
|
+
>
|
|
2422
2543
|
<textarea
|
|
2423
2544
|
pInputTextarea
|
|
2424
2545
|
id="defaultMessage"
|
|
2425
2546
|
[formField]="formTree.defaultMessage"
|
|
2426
2547
|
[rows]="2"
|
|
2427
|
-
[placeholder]="
|
|
2548
|
+
[placeholder]="
|
|
2549
|
+
'localization.placeholder.default.message' | translate
|
|
2550
|
+
"
|
|
2551
|
+
></textarea>
|
|
2428
2552
|
</div>
|
|
2429
2553
|
|
|
2430
2554
|
<!-- Description -->
|
|
2431
2555
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2432
|
-
<label for="description" class="font-medium">{{
|
|
2556
|
+
<label for="description" class="font-medium">{{
|
|
2557
|
+
'localization.key.description' | translate
|
|
2558
|
+
}}</label>
|
|
2433
2559
|
<input
|
|
2434
2560
|
pInputText
|
|
2435
2561
|
id="description"
|
|
2436
2562
|
[formField]="formTree.description"
|
|
2437
|
-
[placeholder]="
|
|
2563
|
+
[placeholder]="
|
|
2564
|
+
'localization.placeholder.key.description' | translate
|
|
2565
|
+
"
|
|
2566
|
+
/>
|
|
2438
2567
|
</div>
|
|
2439
2568
|
|
|
2440
2569
|
<!-- Variables -->
|
|
2441
2570
|
<div class="flex flex-col gap-2 md:col-span-2">
|
|
2442
|
-
<label for="variables" class="font-medium">{{
|
|
2571
|
+
<label for="variables" class="font-medium">{{
|
|
2572
|
+
'localization.key.variables' | translate
|
|
2573
|
+
}}</label>
|
|
2443
2574
|
<input
|
|
2444
2575
|
pInputText
|
|
2445
2576
|
id="variables"
|
|
2446
2577
|
[formField]="formTree.variables"
|
|
2447
|
-
[placeholder]="
|
|
2448
|
-
|
|
2578
|
+
[placeholder]="
|
|
2579
|
+
'localization.key.variables.placeholder' | translate
|
|
2580
|
+
"
|
|
2581
|
+
/>
|
|
2582
|
+
<small class="text-muted-color">{{
|
|
2583
|
+
'localization.key.variables.hint' | translate
|
|
2584
|
+
}}</small>
|
|
2449
2585
|
</div>
|
|
2450
2586
|
</div>
|
|
2451
2587
|
</div>
|
|
2452
2588
|
|
|
2453
2589
|
<!-- Translations Section -->
|
|
2454
2590
|
<div class="p-4 surface-ground rounded-lg">
|
|
2455
|
-
<h4 class="font-semibold mt-0 mb-4">
|
|
2591
|
+
<h4 class="font-semibold mt-0 mb-4">
|
|
2592
|
+
{{ 'localization.key.translations.section' | translate }}
|
|
2593
|
+
</h4>
|
|
2456
2594
|
@if (isLoadingLanguages()) {
|
|
2457
2595
|
<div class="flex justify-center py-4">
|
|
2458
2596
|
<p-progressSpinner strokeWidth="4" />
|
|
@@ -2469,18 +2607,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
2469
2607
|
<label class="font-medium">
|
|
2470
2608
|
{{ lang.name }}
|
|
2471
2609
|
@if (lang.nativeName && lang.nativeName !== lang.name) {
|
|
2472
|
-
<span class="text-muted-color"
|
|
2610
|
+
<span class="text-muted-color"
|
|
2611
|
+
>({{ lang.nativeName }})</span
|
|
2612
|
+
>
|
|
2473
2613
|
}
|
|
2474
2614
|
</label>
|
|
2475
|
-
<p-tag
|
|
2615
|
+
<p-tag
|
|
2616
|
+
[value]="lang.code"
|
|
2617
|
+
severity="secondary"
|
|
2618
|
+
class="uppercase"
|
|
2619
|
+
/>
|
|
2476
2620
|
</div>
|
|
2477
2621
|
<textarea
|
|
2478
2622
|
pInputTextarea
|
|
2479
2623
|
[ngModel]="getTranslationValue(lang.id)"
|
|
2480
2624
|
(ngModelChange)="setTranslationValue(lang.id, $event)"
|
|
2481
|
-
[ngModelOptions]="{standalone: true}"
|
|
2625
|
+
[ngModelOptions]="{ standalone: true }"
|
|
2482
2626
|
[rows]="2"
|
|
2483
|
-
[placeholder]="
|
|
2627
|
+
[placeholder]="
|
|
2628
|
+
formModel().defaultMessage ||
|
|
2629
|
+
('localization.key.enter.translation' | translate)
|
|
2630
|
+
"
|
|
2631
|
+
></textarea>
|
|
2484
2632
|
</div>
|
|
2485
2633
|
}
|
|
2486
2634
|
</div>
|
|
@@ -2493,12 +2641,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
2493
2641
|
[label]="'shared.cancel' | translate"
|
|
2494
2642
|
severity="secondary"
|
|
2495
2643
|
[outlined]="true"
|
|
2496
|
-
(onClick)="onCancel()"
|
|
2644
|
+
(onClick)="onCancel()"
|
|
2645
|
+
/>
|
|
2497
2646
|
<p-button
|
|
2498
|
-
[label]="
|
|
2647
|
+
[label]="
|
|
2648
|
+
isEditMode()
|
|
2649
|
+
? ('shared.update' | translate)
|
|
2650
|
+
: ('shared.create' | translate)
|
|
2651
|
+
"
|
|
2499
2652
|
type="submit"
|
|
2500
2653
|
[loading]="isSaving()"
|
|
2501
|
-
[disabled]="!isFormValid() || isSaving()"
|
|
2654
|
+
[disabled]="!isFormValid() || isSaving()"
|
|
2655
|
+
/>
|
|
2502
2656
|
</div>
|
|
2503
2657
|
</form>
|
|
2504
2658
|
</p-card>
|
|
@@ -2513,511 +2667,11 @@ var translationKeyForm_page = /*#__PURE__*/Object.freeze({
|
|
|
2513
2667
|
TranslationKeyFormPage: TranslationKeyFormPage
|
|
2514
2668
|
});
|
|
2515
2669
|
|
|
2516
|
-
class TranslationListPage {
|
|
2517
|
-
languageService = inject(LanguageApiService);
|
|
2518
|
-
translationKeyService = inject(TranslationKeyApiService);
|
|
2519
|
-
translationService = inject(TranslationApiService);
|
|
2520
|
-
messageService = inject(MessageService);
|
|
2521
|
-
translateService = inject(TranslateService);
|
|
2522
|
-
destroyRef = inject(DestroyRef);
|
|
2523
|
-
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
2524
|
-
isSaving = signal(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
2525
|
-
languages = signal([], ...(ngDevMode ? [{ debugName: "languages" }] : []));
|
|
2526
|
-
modules = signal([], ...(ngDevMode ? [{ debugName: "modules" }] : []));
|
|
2527
|
-
translationRows = signal([], ...(ngDevMode ? [{ debugName: "translationRows" }] : []));
|
|
2528
|
-
selectedModule = signal(null, ...(ngDevMode ? [{ debugName: "selectedModule" }] : []));
|
|
2529
|
-
selectedLanguageId = signal(null, ...(ngDevMode ? [{ debugName: "selectedLanguageId" }] : []));
|
|
2530
|
-
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
2531
|
-
moduleOptions = computed(() => [
|
|
2532
|
-
{ label: this.translateService.instant('localization.translation.all.modules'), value: null },
|
|
2533
|
-
...this.modules().map((m) => ({ label: m, value: m })),
|
|
2534
|
-
], ...(ngDevMode ? [{ debugName: "moduleOptions" }] : []));
|
|
2535
|
-
paginationTemplate = computed(() => this.translateService.instant('localization.translation.pagination'), ...(ngDevMode ? [{ debugName: "paginationTemplate" }] : []));
|
|
2536
|
-
languageOptions = computed(() => this.languages().map((l) => ({
|
|
2537
|
-
label: `${l.name} (${l.code})`,
|
|
2538
|
-
value: l.id,
|
|
2539
|
-
})), ...(ngDevMode ? [{ debugName: "languageOptions" }] : []));
|
|
2540
|
-
filteredRows = computed(() => {
|
|
2541
|
-
const rows = this.translationRows();
|
|
2542
|
-
const search = this.searchTerm().toLowerCase().trim();
|
|
2543
|
-
if (!search)
|
|
2544
|
-
return rows;
|
|
2545
|
-
return rows.filter((r) => r.translationKey.key.toLowerCase().includes(search) ||
|
|
2546
|
-
r.translationKey.defaultMessage.toLowerCase().includes(search) ||
|
|
2547
|
-
r.editValue.toLowerCase().includes(search));
|
|
2548
|
-
}, ...(ngDevMode ? [{ debugName: "filteredRows" }] : []));
|
|
2549
|
-
hasChanges = computed(() => this.translationRows().some((r) => r.isDirty), ...(ngDevMode ? [{ debugName: "hasChanges" }] : []));
|
|
2550
|
-
changedCount = computed(() => this.translationRows().filter((r) => r.isDirty).length, ...(ngDevMode ? [{ debugName: "changedCount" }] : []));
|
|
2551
|
-
formatVariable(v) {
|
|
2552
|
-
return `{{${v}}}`;
|
|
2553
|
-
}
|
|
2554
|
-
ngOnInit() {
|
|
2555
|
-
this.loadInitialData();
|
|
2556
|
-
}
|
|
2557
|
-
loadInitialData() {
|
|
2558
|
-
this.isLoading.set(true);
|
|
2559
|
-
forkJoin({
|
|
2560
|
-
languages: this.languageService.getAll(),
|
|
2561
|
-
modules: this.translationKeyService.getModules(),
|
|
2562
|
-
})
|
|
2563
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2564
|
-
.subscribe({
|
|
2565
|
-
next: ({ languages, modules }) => {
|
|
2566
|
-
if (languages.success && languages.data) {
|
|
2567
|
-
this.languages.set(languages.data.filter((l) => l.isActive));
|
|
2568
|
-
const defaultLang = languages.data.find((l) => l.isDefault);
|
|
2569
|
-
if (defaultLang) {
|
|
2570
|
-
this.selectedLanguageId.set(defaultLang.id);
|
|
2571
|
-
}
|
|
2572
|
-
else if (languages.data.length > 0) {
|
|
2573
|
-
this.selectedLanguageId.set(languages.data[0].id);
|
|
2574
|
-
}
|
|
2575
|
-
}
|
|
2576
|
-
if (modules.success && modules.data) {
|
|
2577
|
-
this.modules.set(modules.data);
|
|
2578
|
-
}
|
|
2579
|
-
this.isLoading.set(false);
|
|
2580
|
-
},
|
|
2581
|
-
error: () => {
|
|
2582
|
-
this.isLoading.set(false);
|
|
2583
|
-
},
|
|
2584
|
-
});
|
|
2585
|
-
}
|
|
2586
|
-
onModuleChange(value) {
|
|
2587
|
-
this.selectedModule.set(value);
|
|
2588
|
-
this.loadTranslations();
|
|
2589
|
-
}
|
|
2590
|
-
onLanguageChange(value) {
|
|
2591
|
-
this.selectedLanguageId.set(value);
|
|
2592
|
-
this.loadTranslations();
|
|
2593
|
-
}
|
|
2594
|
-
loadTranslations() {
|
|
2595
|
-
const languageId = this.selectedLanguageId();
|
|
2596
|
-
if (!languageId) {
|
|
2597
|
-
this.translationRows.set([]);
|
|
2598
|
-
return;
|
|
2599
|
-
}
|
|
2600
|
-
this.isLoading.set(true);
|
|
2601
|
-
const module = this.selectedModule();
|
|
2602
|
-
const keysRequest = module
|
|
2603
|
-
? this.translationKeyService.getByModule(module)
|
|
2604
|
-
: this.translationKeyService.getAll();
|
|
2605
|
-
const translationsRequest = module
|
|
2606
|
-
? this.translationService.getByModuleAndLanguageId(module, languageId)
|
|
2607
|
-
: this.translationService.getByLanguageId(languageId);
|
|
2608
|
-
forkJoin({
|
|
2609
|
-
keys: keysRequest,
|
|
2610
|
-
translations: translationsRequest,
|
|
2611
|
-
})
|
|
2612
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2613
|
-
.subscribe({
|
|
2614
|
-
next: ({ keys, translations }) => {
|
|
2615
|
-
const translationMap = new Map();
|
|
2616
|
-
if (translations.success && translations.data) {
|
|
2617
|
-
translations.data.forEach((t) => {
|
|
2618
|
-
translationMap.set(t.translationKeyId, t);
|
|
2619
|
-
});
|
|
2620
|
-
}
|
|
2621
|
-
const rows = [];
|
|
2622
|
-
if (keys.success && keys.data) {
|
|
2623
|
-
keys.data.forEach((key) => {
|
|
2624
|
-
const translation = translationMap.get(key.id) ?? null;
|
|
2625
|
-
rows.push({
|
|
2626
|
-
translationKey: key,
|
|
2627
|
-
translation,
|
|
2628
|
-
editValue: translation?.value ?? '',
|
|
2629
|
-
isVerified: translation?.isVerified ?? false,
|
|
2630
|
-
isDirty: false,
|
|
2631
|
-
});
|
|
2632
|
-
});
|
|
2633
|
-
}
|
|
2634
|
-
this.translationRows.set(rows);
|
|
2635
|
-
this.isLoading.set(false);
|
|
2636
|
-
},
|
|
2637
|
-
error: () => {
|
|
2638
|
-
this.isLoading.set(false);
|
|
2639
|
-
},
|
|
2640
|
-
});
|
|
2641
|
-
}
|
|
2642
|
-
onValueChange(row) {
|
|
2643
|
-
const originalValue = row.translation?.value ?? '';
|
|
2644
|
-
const originalVerified = row.translation?.isVerified ?? false;
|
|
2645
|
-
row.isDirty = row.editValue !== originalValue || row.isVerified !== originalVerified;
|
|
2646
|
-
this.translationRows.update((rows) => [...rows]);
|
|
2647
|
-
}
|
|
2648
|
-
onVerifiedChange(row) {
|
|
2649
|
-
this.onValueChange(row);
|
|
2650
|
-
}
|
|
2651
|
-
saveChanges() {
|
|
2652
|
-
const changedRows = this.translationRows().filter((r) => r.isDirty);
|
|
2653
|
-
const languageId = this.selectedLanguageId();
|
|
2654
|
-
if (changedRows.length === 0 || !languageId)
|
|
2655
|
-
return;
|
|
2656
|
-
this.isSaving.set(true);
|
|
2657
|
-
const items = changedRows.map((row) => ({
|
|
2658
|
-
id: row.translation?.id,
|
|
2659
|
-
languageId,
|
|
2660
|
-
translationKeyId: row.translationKey.id,
|
|
2661
|
-
value: row.editValue,
|
|
2662
|
-
isVerified: row.isVerified,
|
|
2663
|
-
}));
|
|
2664
|
-
this.translationService
|
|
2665
|
-
.bulkUpdate(items)
|
|
2666
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2667
|
-
.subscribe({
|
|
2668
|
-
next: (response) => {
|
|
2669
|
-
if (response.success) {
|
|
2670
|
-
this.messageService.add({
|
|
2671
|
-
severity: 'success',
|
|
2672
|
-
summary: this.translateService.instant('localization.translation.save.success'),
|
|
2673
|
-
detail: this.translateService.instant('localization.translation.save.success.detail'),
|
|
2674
|
-
});
|
|
2675
|
-
this.loadTranslations();
|
|
2676
|
-
}
|
|
2677
|
-
this.isSaving.set(false);
|
|
2678
|
-
},
|
|
2679
|
-
error: () => {
|
|
2680
|
-
this.isSaving.set(false);
|
|
2681
|
-
},
|
|
2682
|
-
});
|
|
2683
|
-
}
|
|
2684
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationListPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2685
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: TranslationListPage, isStandalone: true, selector: "lib-translation-list-page", providers: [MessageService], ngImport: i0, template: `
|
|
2686
|
-
<div class="card">
|
|
2687
|
-
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
|
|
2688
|
-
<h2 class="text-xl font-semibold m-0">{{ 'localization.translation.title' | translate }}</h2>
|
|
2689
|
-
<div class="flex gap-2">
|
|
2690
|
-
<p-button
|
|
2691
|
-
[label]="'shared.save' | translate"
|
|
2692
|
-
icon="pi pi-save"
|
|
2693
|
-
[disabled]="!hasChanges()"
|
|
2694
|
-
[loading]="isSaving()"
|
|
2695
|
-
(onClick)="saveChanges()"
|
|
2696
|
-
/>
|
|
2697
|
-
</div>
|
|
2698
|
-
</div>
|
|
2699
|
-
|
|
2700
|
-
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
2701
|
-
<div class="flex-1">
|
|
2702
|
-
<label class="block font-medium mb-2">{{ 'localization.translation.module' | translate }}</label>
|
|
2703
|
-
<p-select
|
|
2704
|
-
[options]="moduleOptions()"
|
|
2705
|
-
[ngModel]="selectedModule()"
|
|
2706
|
-
(ngModelChange)="onModuleChange($event)"
|
|
2707
|
-
[ngModelOptions]="{standalone: true}"
|
|
2708
|
-
optionLabel="label"
|
|
2709
|
-
optionValue="value"
|
|
2710
|
-
[placeholder]="'localization.translation.select.module' | translate"
|
|
2711
|
-
class="w-full"
|
|
2712
|
-
/>
|
|
2713
|
-
</div>
|
|
2714
|
-
<div class="flex-1">
|
|
2715
|
-
<label class="block font-medium mb-2">{{ 'localization.translation.language' | translate }}</label>
|
|
2716
|
-
<p-select
|
|
2717
|
-
[options]="languageOptions()"
|
|
2718
|
-
[ngModel]="selectedLanguageId()"
|
|
2719
|
-
(ngModelChange)="onLanguageChange($event)"
|
|
2720
|
-
[ngModelOptions]="{standalone: true}"
|
|
2721
|
-
optionLabel="label"
|
|
2722
|
-
optionValue="value"
|
|
2723
|
-
[placeholder]="'localization.translation.select.language' | translate"
|
|
2724
|
-
class="w-full"
|
|
2725
|
-
/>
|
|
2726
|
-
</div>
|
|
2727
|
-
<div class="flex-1">
|
|
2728
|
-
<label class="block font-medium mb-2">{{ 'shared.search' | translate }}</label>
|
|
2729
|
-
<p-iconfield class="w-full">
|
|
2730
|
-
<p-inputicon class="pi pi-search" />
|
|
2731
|
-
<input
|
|
2732
|
-
pInputText
|
|
2733
|
-
[ngModel]="searchTerm()"
|
|
2734
|
-
(ngModelChange)="searchTerm.set($event)"
|
|
2735
|
-
[ngModelOptions]="{standalone: true}"
|
|
2736
|
-
[placeholder]="'localization.translation.search.keys' | translate"
|
|
2737
|
-
class="w-full"
|
|
2738
|
-
/>
|
|
2739
|
-
</p-iconfield>
|
|
2740
|
-
</div>
|
|
2741
|
-
</div>
|
|
2742
|
-
|
|
2743
|
-
@if (isLoading()) {
|
|
2744
|
-
<div class="flex justify-center py-8">
|
|
2745
|
-
<p-progressSpinner strokeWidth="4" />
|
|
2746
|
-
</div>
|
|
2747
|
-
} @else if (!selectedLanguageId()) {
|
|
2748
|
-
<div class="text-center py-8 text-muted-color">
|
|
2749
|
-
<p>{{ 'localization.translation.select.language.hint' | translate }}</p>
|
|
2750
|
-
</div>
|
|
2751
|
-
} @else if (filteredRows().length === 0) {
|
|
2752
|
-
<div class="text-center py-8 text-muted-color">
|
|
2753
|
-
<p>{{ 'localization.translation.no.keys' | translate }}</p>
|
|
2754
|
-
</div>
|
|
2755
|
-
} @else {
|
|
2756
|
-
<p-table
|
|
2757
|
-
[value]="filteredRows()"
|
|
2758
|
-
[paginator]="true"
|
|
2759
|
-
[rows]="20"
|
|
2760
|
-
[rowsPerPageOptions]="[10, 20, 50, 100]"
|
|
2761
|
-
[showCurrentPageReport]="true"
|
|
2762
|
-
[currentPageReportTemplate]="paginationTemplate()"
|
|
2763
|
-
styleClass="p-datatable-sm"
|
|
2764
|
-
>
|
|
2765
|
-
<ng-template #header>
|
|
2766
|
-
<tr>
|
|
2767
|
-
<th style="width: 30%">{{ 'localization.translation.key' | translate }}</th>
|
|
2768
|
-
<th style="width: 25%">{{ 'localization.translation.default.message' | translate }}</th>
|
|
2769
|
-
<th style="width: 35%">{{ 'localization.translation.value' | translate }}</th>
|
|
2770
|
-
<th style="width: 10%">{{ 'localization.translation.verified' | translate }}</th>
|
|
2771
|
-
</tr>
|
|
2772
|
-
</ng-template>
|
|
2773
|
-
<ng-template #body let-row>
|
|
2774
|
-
<tr [class.bg-yellow-50]="row.isDirty">
|
|
2775
|
-
<td>
|
|
2776
|
-
<div class="font-medium text-sm">{{ row.translationKey.key }}</div>
|
|
2777
|
-
@if (row.translationKey.description) {
|
|
2778
|
-
<small class="text-muted-color">{{ row.translationKey.description }}</small>
|
|
2779
|
-
}
|
|
2780
|
-
@if (row.translationKey.variables?.length) {
|
|
2781
|
-
<div class="mt-1">
|
|
2782
|
-
@for (v of row.translationKey.variables; track v) {
|
|
2783
|
-
<span class="text-xs bg-surface-100 px-2 py-1 rounded mr-1">{{ formatVariable(v) }}</span>
|
|
2784
|
-
}
|
|
2785
|
-
</div>
|
|
2786
|
-
}
|
|
2787
|
-
</td>
|
|
2788
|
-
<td>
|
|
2789
|
-
<span class="text-sm">{{ row.translationKey.defaultMessage }}</span>
|
|
2790
|
-
</td>
|
|
2791
|
-
<td>
|
|
2792
|
-
<textarea
|
|
2793
|
-
pInputTextarea
|
|
2794
|
-
[(ngModel)]="row.editValue"
|
|
2795
|
-
[ngModelOptions]="{standalone: true}"
|
|
2796
|
-
[rows]="2"
|
|
2797
|
-
class="w-full"
|
|
2798
|
-
[placeholder]="row.translationKey.defaultMessage"
|
|
2799
|
-
(input)="onValueChange(row)"
|
|
2800
|
-
></textarea>
|
|
2801
|
-
</td>
|
|
2802
|
-
<td class="text-center">
|
|
2803
|
-
<p-checkbox
|
|
2804
|
-
[(ngModel)]="row.isVerified"
|
|
2805
|
-
[ngModelOptions]="{standalone: true}"
|
|
2806
|
-
[binary]="true"
|
|
2807
|
-
(onChange)="onVerifiedChange(row)"
|
|
2808
|
-
/>
|
|
2809
|
-
</td>
|
|
2810
|
-
</tr>
|
|
2811
|
-
</ng-template>
|
|
2812
|
-
<ng-template #emptymessage>
|
|
2813
|
-
<tr>
|
|
2814
|
-
<td colspan="4" class="text-center py-4 text-muted-color">
|
|
2815
|
-
{{ 'shared.no.results' | translate }}
|
|
2816
|
-
</td>
|
|
2817
|
-
</tr>
|
|
2818
|
-
</ng-template>
|
|
2819
|
-
</p-table>
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2822
|
-
<div class="flex justify-between items-center mt-4">
|
|
2823
|
-
<div class="text-muted-color">
|
|
2824
|
-
@if (hasChanges()) {
|
|
2825
|
-
<span class="text-orange-500">
|
|
2826
|
-
<i class="pi pi-exclamation-circle mr-1"></i>
|
|
2827
|
-
{{ 'localization.translation.unsaved.changes' | translate: { count: changedCount() } }}
|
|
2828
|
-
</span>
|
|
2829
|
-
}
|
|
2830
|
-
</div>
|
|
2831
|
-
<p-button
|
|
2832
|
-
[label]="'shared.save' | translate"
|
|
2833
|
-
icon="pi pi-save"
|
|
2834
|
-
[disabled]="!hasChanges()"
|
|
2835
|
-
[loading]="isSaving()"
|
|
2836
|
-
(onClick)="saveChanges()"
|
|
2837
|
-
/>
|
|
2838
|
-
</div>
|
|
2839
|
-
</div>
|
|
2840
|
-
|
|
2841
|
-
<p-toast />
|
|
2842
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i3$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "component", type: i4$2.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i5$1.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i8.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i7.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type: i10.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "motionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "component", type: i9.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
2843
|
-
}
|
|
2844
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: TranslationListPage, decorators: [{
|
|
2845
|
-
type: Component,
|
|
2846
|
-
args: [{
|
|
2847
|
-
selector: 'lib-translation-list-page',
|
|
2848
|
-
imports: [AngularModule, PrimeModule, FormsModule, TranslatePipe],
|
|
2849
|
-
providers: [MessageService],
|
|
2850
|
-
template: `
|
|
2851
|
-
<div class="card">
|
|
2852
|
-
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-4">
|
|
2853
|
-
<h2 class="text-xl font-semibold m-0">{{ 'localization.translation.title' | translate }}</h2>
|
|
2854
|
-
<div class="flex gap-2">
|
|
2855
|
-
<p-button
|
|
2856
|
-
[label]="'shared.save' | translate"
|
|
2857
|
-
icon="pi pi-save"
|
|
2858
|
-
[disabled]="!hasChanges()"
|
|
2859
|
-
[loading]="isSaving()"
|
|
2860
|
-
(onClick)="saveChanges()"
|
|
2861
|
-
/>
|
|
2862
|
-
</div>
|
|
2863
|
-
</div>
|
|
2864
|
-
|
|
2865
|
-
<div class="flex flex-col md:flex-row gap-4 mb-4">
|
|
2866
|
-
<div class="flex-1">
|
|
2867
|
-
<label class="block font-medium mb-2">{{ 'localization.translation.module' | translate }}</label>
|
|
2868
|
-
<p-select
|
|
2869
|
-
[options]="moduleOptions()"
|
|
2870
|
-
[ngModel]="selectedModule()"
|
|
2871
|
-
(ngModelChange)="onModuleChange($event)"
|
|
2872
|
-
[ngModelOptions]="{standalone: true}"
|
|
2873
|
-
optionLabel="label"
|
|
2874
|
-
optionValue="value"
|
|
2875
|
-
[placeholder]="'localization.translation.select.module' | translate"
|
|
2876
|
-
class="w-full"
|
|
2877
|
-
/>
|
|
2878
|
-
</div>
|
|
2879
|
-
<div class="flex-1">
|
|
2880
|
-
<label class="block font-medium mb-2">{{ 'localization.translation.language' | translate }}</label>
|
|
2881
|
-
<p-select
|
|
2882
|
-
[options]="languageOptions()"
|
|
2883
|
-
[ngModel]="selectedLanguageId()"
|
|
2884
|
-
(ngModelChange)="onLanguageChange($event)"
|
|
2885
|
-
[ngModelOptions]="{standalone: true}"
|
|
2886
|
-
optionLabel="label"
|
|
2887
|
-
optionValue="value"
|
|
2888
|
-
[placeholder]="'localization.translation.select.language' | translate"
|
|
2889
|
-
class="w-full"
|
|
2890
|
-
/>
|
|
2891
|
-
</div>
|
|
2892
|
-
<div class="flex-1">
|
|
2893
|
-
<label class="block font-medium mb-2">{{ 'shared.search' | translate }}</label>
|
|
2894
|
-
<p-iconfield class="w-full">
|
|
2895
|
-
<p-inputicon class="pi pi-search" />
|
|
2896
|
-
<input
|
|
2897
|
-
pInputText
|
|
2898
|
-
[ngModel]="searchTerm()"
|
|
2899
|
-
(ngModelChange)="searchTerm.set($event)"
|
|
2900
|
-
[ngModelOptions]="{standalone: true}"
|
|
2901
|
-
[placeholder]="'localization.translation.search.keys' | translate"
|
|
2902
|
-
class="w-full"
|
|
2903
|
-
/>
|
|
2904
|
-
</p-iconfield>
|
|
2905
|
-
</div>
|
|
2906
|
-
</div>
|
|
2907
|
-
|
|
2908
|
-
@if (isLoading()) {
|
|
2909
|
-
<div class="flex justify-center py-8">
|
|
2910
|
-
<p-progressSpinner strokeWidth="4" />
|
|
2911
|
-
</div>
|
|
2912
|
-
} @else if (!selectedLanguageId()) {
|
|
2913
|
-
<div class="text-center py-8 text-muted-color">
|
|
2914
|
-
<p>{{ 'localization.translation.select.language.hint' | translate }}</p>
|
|
2915
|
-
</div>
|
|
2916
|
-
} @else if (filteredRows().length === 0) {
|
|
2917
|
-
<div class="text-center py-8 text-muted-color">
|
|
2918
|
-
<p>{{ 'localization.translation.no.keys' | translate }}</p>
|
|
2919
|
-
</div>
|
|
2920
|
-
} @else {
|
|
2921
|
-
<p-table
|
|
2922
|
-
[value]="filteredRows()"
|
|
2923
|
-
[paginator]="true"
|
|
2924
|
-
[rows]="20"
|
|
2925
|
-
[rowsPerPageOptions]="[10, 20, 50, 100]"
|
|
2926
|
-
[showCurrentPageReport]="true"
|
|
2927
|
-
[currentPageReportTemplate]="paginationTemplate()"
|
|
2928
|
-
styleClass="p-datatable-sm"
|
|
2929
|
-
>
|
|
2930
|
-
<ng-template #header>
|
|
2931
|
-
<tr>
|
|
2932
|
-
<th style="width: 30%">{{ 'localization.translation.key' | translate }}</th>
|
|
2933
|
-
<th style="width: 25%">{{ 'localization.translation.default.message' | translate }}</th>
|
|
2934
|
-
<th style="width: 35%">{{ 'localization.translation.value' | translate }}</th>
|
|
2935
|
-
<th style="width: 10%">{{ 'localization.translation.verified' | translate }}</th>
|
|
2936
|
-
</tr>
|
|
2937
|
-
</ng-template>
|
|
2938
|
-
<ng-template #body let-row>
|
|
2939
|
-
<tr [class.bg-yellow-50]="row.isDirty">
|
|
2940
|
-
<td>
|
|
2941
|
-
<div class="font-medium text-sm">{{ row.translationKey.key }}</div>
|
|
2942
|
-
@if (row.translationKey.description) {
|
|
2943
|
-
<small class="text-muted-color">{{ row.translationKey.description }}</small>
|
|
2944
|
-
}
|
|
2945
|
-
@if (row.translationKey.variables?.length) {
|
|
2946
|
-
<div class="mt-1">
|
|
2947
|
-
@for (v of row.translationKey.variables; track v) {
|
|
2948
|
-
<span class="text-xs bg-surface-100 px-2 py-1 rounded mr-1">{{ formatVariable(v) }}</span>
|
|
2949
|
-
}
|
|
2950
|
-
</div>
|
|
2951
|
-
}
|
|
2952
|
-
</td>
|
|
2953
|
-
<td>
|
|
2954
|
-
<span class="text-sm">{{ row.translationKey.defaultMessage }}</span>
|
|
2955
|
-
</td>
|
|
2956
|
-
<td>
|
|
2957
|
-
<textarea
|
|
2958
|
-
pInputTextarea
|
|
2959
|
-
[(ngModel)]="row.editValue"
|
|
2960
|
-
[ngModelOptions]="{standalone: true}"
|
|
2961
|
-
[rows]="2"
|
|
2962
|
-
class="w-full"
|
|
2963
|
-
[placeholder]="row.translationKey.defaultMessage"
|
|
2964
|
-
(input)="onValueChange(row)"
|
|
2965
|
-
></textarea>
|
|
2966
|
-
</td>
|
|
2967
|
-
<td class="text-center">
|
|
2968
|
-
<p-checkbox
|
|
2969
|
-
[(ngModel)]="row.isVerified"
|
|
2970
|
-
[ngModelOptions]="{standalone: true}"
|
|
2971
|
-
[binary]="true"
|
|
2972
|
-
(onChange)="onVerifiedChange(row)"
|
|
2973
|
-
/>
|
|
2974
|
-
</td>
|
|
2975
|
-
</tr>
|
|
2976
|
-
</ng-template>
|
|
2977
|
-
<ng-template #emptymessage>
|
|
2978
|
-
<tr>
|
|
2979
|
-
<td colspan="4" class="text-center py-4 text-muted-color">
|
|
2980
|
-
{{ 'shared.no.results' | translate }}
|
|
2981
|
-
</td>
|
|
2982
|
-
</tr>
|
|
2983
|
-
</ng-template>
|
|
2984
|
-
</p-table>
|
|
2985
|
-
}
|
|
2986
|
-
|
|
2987
|
-
<div class="flex justify-between items-center mt-4">
|
|
2988
|
-
<div class="text-muted-color">
|
|
2989
|
-
@if (hasChanges()) {
|
|
2990
|
-
<span class="text-orange-500">
|
|
2991
|
-
<i class="pi pi-exclamation-circle mr-1"></i>
|
|
2992
|
-
{{ 'localization.translation.unsaved.changes' | translate: { count: changedCount() } }}
|
|
2993
|
-
</span>
|
|
2994
|
-
}
|
|
2995
|
-
</div>
|
|
2996
|
-
<p-button
|
|
2997
|
-
[label]="'shared.save' | translate"
|
|
2998
|
-
icon="pi pi-save"
|
|
2999
|
-
[disabled]="!hasChanges()"
|
|
3000
|
-
[loading]="isSaving()"
|
|
3001
|
-
(onClick)="saveChanges()"
|
|
3002
|
-
/>
|
|
3003
|
-
</div>
|
|
3004
|
-
</div>
|
|
3005
|
-
|
|
3006
|
-
<p-toast />
|
|
3007
|
-
`,
|
|
3008
|
-
}]
|
|
3009
|
-
}] });
|
|
3010
|
-
|
|
3011
|
-
var translationList_page = /*#__PURE__*/Object.freeze({
|
|
3012
|
-
__proto__: null,
|
|
3013
|
-
TranslationListPage: TranslationListPage
|
|
3014
|
-
});
|
|
3015
|
-
|
|
3016
2670
|
// Interfaces
|
|
3017
2671
|
|
|
3018
2672
|
/**
|
|
3019
2673
|
* Generated bundle index. Do not edit.
|
|
3020
2674
|
*/
|
|
3021
2675
|
|
|
3022
|
-
export { LOCALIZATION_CONFIG, LOCALIZATION_MESSAGES, LOCALIZATION_ROUTES, LanguageApiService, LanguageFormPage, LanguageListPage, LanguageSelectorComponent, LocalizationApiService, LocalizationContainerPage, LocalizationInitializerService, LocalizationStateService, STORAGE_KEYS, TranslateService, TranslationApiService, TranslationKeyApiService, TranslationKeyFormPage, TranslationKeyListPage,
|
|
2676
|
+
export { LOCALIZATION_CONFIG, LOCALIZATION_MESSAGES, LOCALIZATION_ROUTES, LanguageApiService, LanguageFormPage, LanguageListPage, LanguageSelectorComponent, LocalizationApiService, LocalizationContainerPage, LocalizationInitializerService, LocalizationStateService, STORAGE_KEYS, TranslateService, TranslationApiService, TranslationKeyApiService, TranslationKeyFormPage, TranslationKeyListPage, TranslationLoaderService, getLocalizationConfig, provideLocalization };
|
|
3023
2677
|
//# sourceMappingURL=flusys-ng-localization.mjs.map
|