@flusys/ng-localization 9.1.1 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (16) hide show
  1. package/fesm2022/{flusys-ng-localization-language-form.page-BdxZ6meb.mjs → flusys-ng-localization-language-form.page-DB-cn7MO.mjs} +24 -20
  2. package/fesm2022/flusys-ng-localization-language-form.page-DB-cn7MO.mjs.map +1 -0
  3. package/fesm2022/{flusys-ng-localization-language-list.page-B8wnYNNd.mjs → flusys-ng-localization-language-list.page-CfM-mc9g.mjs} +29 -21
  4. package/fesm2022/{flusys-ng-localization-language-list.page-B8wnYNNd.mjs.map → flusys-ng-localization-language-list.page-CfM-mc9g.mjs.map} +1 -1
  5. package/fesm2022/flusys-ng-localization-localization-container.page-CsrYVvth.mjs.map +1 -1
  6. package/fesm2022/{flusys-ng-localization-translation-key-form.page-Dgn58Sh7.mjs → flusys-ng-localization-translation-key-form.page-BCkDs0tt.mjs} +43 -36
  7. package/fesm2022/flusys-ng-localization-translation-key-form.page-BCkDs0tt.mjs.map +1 -0
  8. package/fesm2022/{flusys-ng-localization-translation-key-list.page-DhRI5UvT.mjs → flusys-ng-localization-translation-key-list.page-CGC5125Z.mjs} +28 -15
  9. package/fesm2022/flusys-ng-localization-translation-key-list.page-CGC5125Z.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-localization.mjs +42 -19
  11. package/fesm2022/flusys-ng-localization.mjs.map +1 -1
  12. package/package.json +5 -5
  13. package/types/flusys-ng-localization.d.ts +2 -0
  14. package/fesm2022/flusys-ng-localization-language-form.page-BdxZ6meb.mjs.map +0 -1
  15. package/fesm2022/flusys-ng-localization-translation-key-form.page-Dgn58Sh7.mjs.map +0 -1
  16. package/fesm2022/flusys-ng-localization-translation-key-list.page-DhRI5UvT.mjs.map +0 -1
@@ -25,6 +25,8 @@ var TranslationKeyListPage = class TranslationKeyListPage {
25
25
  translationCounts = signal(/* @__PURE__ */ new Map(), ...ngDevMode ? [{ debugName: "translationCounts" }] : /* istanbul ignore next */ []);
26
26
  selectedModule = signal(null, ...ngDevMode ? [{ debugName: "selectedModule" }] : /* istanbul ignore next */ []);
27
27
  searchTerm = signal("", ...ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []);
28
+ loadSeq = 0;
29
+ countsSeq = 0;
28
30
  moduleOptions = computed(() => [{
29
31
  label: this.translateService.translate("shared.all"),
30
32
  value: null
@@ -44,6 +46,7 @@ var TranslationKeyListPage = class TranslationKeyListPage {
44
46
  this.loadData();
45
47
  }
46
48
  loadData() {
49
+ const seq = ++this.loadSeq;
47
50
  this.isLoading.set(true);
48
51
  forkJoin({
49
52
  languages: from(this.languageService.getAll({
@@ -71,6 +74,7 @@ var TranslationKeyListPage = class TranslationKeyListPage {
71
74
  }))
72
75
  }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
73
76
  next: ({ languages, modules, keys }) => {
77
+ if (seq !== this.loadSeq) return;
74
78
  if (languages.success && languages.data) this.languages.set(languages.data.filter((l) => l.isActive));
75
79
  if (modules.success && modules.data) this.modules.set(modules.data);
76
80
  if (keys.success && keys.data) {
@@ -80,14 +84,19 @@ var TranslationKeyListPage = class TranslationKeyListPage {
80
84
  this.isLoading.set(false);
81
85
  },
82
86
  error: () => {
83
- this.isLoading.set(false);
87
+ if (seq === this.loadSeq) this.isLoading.set(false);
84
88
  }
85
89
  });
86
90
  }
87
91
  loadTranslationCounts() {
88
- this.translationService.getCounts().pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ next: (response) => {
89
- if (response.success && response.data) this.translationCounts.set(new Map(Object.entries(response.data)));
90
- } });
92
+ const seq = ++this.countsSeq;
93
+ this.translationService.getCounts().pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
94
+ next: (response) => {
95
+ if (seq !== this.countsSeq) return;
96
+ if (response.success && response.data) this.translationCounts.set(new Map(Object.entries(response.data)));
97
+ },
98
+ error: () => void 0
99
+ });
91
100
  }
92
101
  getTranslationCount(keyId) {
93
102
  return this.translationCounts().get(keyId) ?? 0;
@@ -102,6 +111,7 @@ var TranslationKeyListPage = class TranslationKeyListPage {
102
111
  this.router.navigate(["/localization/keys", key.id]);
103
112
  }
104
113
  onDelete(key) {
114
+ if (key.isReadonly) return;
105
115
  this.confirmationService.confirm({
106
116
  message: this.translateService.translate("shared.confirm.delete"),
107
117
  header: this.translateService.translate("localization.key.delete.title"),
@@ -111,16 +121,19 @@ var TranslationKeyListPage = class TranslationKeyListPage {
111
121
  from(this.translationKeyService.delete({
112
122
  id: key.id,
113
123
  type: "delete"
114
- })).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({ next: (response) => {
115
- if (response.success) {
116
- this.messageService.add({
117
- severity: "success",
118
- summary: this.translateService.translate("shared.success"),
119
- detail: response.messageKey ? this.translateService.translate(response.messageKey, response.messageVariables) : response.message ?? ""
120
- });
121
- this.loadData();
122
- }
123
- } });
124
+ })).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
125
+ next: (response) => {
126
+ if (response.success) {
127
+ this.messageService.add({
128
+ severity: "success",
129
+ summary: this.translateService.translate("shared.success"),
130
+ detail: response.messageKey ? this.translateService.translate(response.messageKey, response.messageVariables) : response.message ?? ""
131
+ });
132
+ this.loadData();
133
+ }
134
+ },
135
+ error: () => void 0
136
+ });
124
137
  }
125
138
  });
126
139
  }
@@ -735,4 +748,4 @@ i0.ɵɵngDeclareClassMetadata({
735
748
  });
736
749
  export { TranslationKeyListPage };
737
750
 
738
- //# sourceMappingURL=flusys-ng-localization-translation-key-list.page-DhRI5UvT.mjs.map
751
+ //# sourceMappingURL=flusys-ng-localization-translation-key-list.page-CGC5125Z.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-localization-translation-key-list.page-CGC5125Z.mjs","names":[],"sources":["../../../projects/ng-localization/pages/translation-key-list/translation-key-list.page.ts"],"sourcesContent":["import {\n Component,\n computed,\n DestroyRef,\n inject,\n OnInit,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormsModule } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport {\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n TRANSLATION_KEY_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport {\n ConfirmationService,\n FButtonDirective,\n IconFieldComponent,\n InputIconComponent,\n InputTextDirective,\n MessageService,\n SelectComponent,\n TableComponent,\n TagComponent,\n TooltipDirective,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport { forkJoin, from } from 'rxjs';\nimport { ILanguage } from '../../interfaces/language.interface';\nimport { ITranslationKey } from '../../interfaces/translation-key.interface';\nimport { LanguageApiService } from '../../services/language-api.service';\nimport { TranslationApiService } from '../../services/translation-api.service';\nimport { TranslationKeyApiService } from '../../services/translation-key-api.service';\n\n@Component({\n selector: 'lib-translation-key-list-page',\n imports: [\n FButtonDirective,\n UiIconComponent,\n SelectComponent,\n IconFieldComponent,\n InputIconComponent,\n InputTextDirective,\n TableComponent,\n TagComponent,\n TooltipDirective,\n FormsModule,\n HasPermissionDirective,\n TranslatePipe,\n ],\n template: `\n <div class=\"card\">\n <div\n class=\"flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 mb-4\"\n >\n <div>\n <h3 class=\"text-lg sm:text-xl font-semibold m-0\">\n {{ 'localization.key.title' | translate }}\n </h3>\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'localization.key.subtitle' | translate }}\n </p>\n </div>\n <div class=\"flex gap-2\">\n <button\n fButton\n *hasPermission=\"TRANSLATION_KEY_PERMISSIONS.CREATE\"\n (click)=\"onCreate()\"\n >\n <ui-icon pButtonIcon name=\"plus\"></ui-icon>\n <span pButtonLabel>{{ 'localization.key.new' | translate }}</span>\n </button>\n </div>\n </div>\n\n <div class=\"flex flex-col md:flex-row gap-4 mb-4\">\n <div class=\"flex-1\">\n <f-select\n [options]=\"moduleOptions()\"\n [ngModel]=\"selectedModule()\"\n (ngModelChange)=\"onModuleChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [placeholder]=\"'localization.key.filter.module' | translate\"\n [showClear]=\"true\"\n class=\"w-full\"\n />\n </div>\n <div class=\"flex-1\">\n <f-iconfield class=\"w-full\">\n <f-inputicon icon=\"search\" />\n <input\n fInputText\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"'shared.search' | translate\"\n class=\"w-full\"\n />\n </f-iconfield>\n </div>\n </div>\n\n <!-- Table -->\n <f-table\n [value]=\"filteredKeys()\"\n [loading]=\"isLoading()\"\n [paginator]=\"true\"\n [rows]=\"15\"\n [rowsPerPageOptions]=\"[10, 15, 25, 50]\"\n >\n <ng-template #header>\n <tr>\n <th style=\"width: 15%\">\n {{ 'localization.key.module' | translate }}\n </th>\n <th style=\"width: 25%\">\n {{ 'localization.key.name' | translate }}\n </th>\n <th style=\"width: 35%\">\n {{ 'localization.key.default.message' | translate }}\n </th>\n <th style=\"width: 10%\">\n {{ 'localization.key.translations' | translate }}\n </th>\n <th style=\"width: 15%\">{{ 'shared.actions' | translate }}</th>\n </tr>\n </ng-template>\n <ng-template #body let-key>\n @let translationCount = getTranslationCount(key.id);\n @let languageCount = languages().length;\n <tr>\n <td>\n <f-tag [value]=\"key.module\" severity=\"secondary\" />\n </td>\n <td>\n <div class=\"flex items-center gap-2\">\n <span class=\"font-medium\">{{ key.key }}</span>\n @if (key.isReadonly) {\n <f-tag\n [value]=\"'shared.read.only' | translate\"\n severity=\"warn\"\n />\n }\n </div>\n @if (key.description) {\n <small class=\"text-muted-color\">{{ key.description }}</small>\n }\n </td>\n <td>{{ key.defaultMessage }}</td>\n <td class=\"text-center\">\n <span\n class=\"text-sm\"\n [class.text-green-500]=\"translationCount === languageCount\"\n [class.text-orange-500]=\"\n translationCount < languageCount && translationCount > 0\n \"\n [class.text-muted-color]=\"translationCount === 0\"\n >\n {{ translationCount }}/{{ languageCount }}\n </span>\n </td>\n <td>\n <div class=\"flex gap-1\">\n <button\n fButton\n *hasPermission=\"TRANSLATION_KEY_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n [fTooltip]=\"'shared.edit' | translate\"\n (click)=\"onEdit(key)\"\n >\n <ui-icon pButtonIcon name=\"pencil\"></ui-icon>\n </button>\n <button\n fButton\n *hasPermission=\"TRANSLATION_KEY_PERMISSIONS.DELETE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n [disabled]=\"key.isReadonly\"\n [fTooltip]=\"\n (key.isReadonly\n ? 'localization.key.readonly.delete.forbidden'\n : 'shared.delete'\n ) | translate\n \"\n (click)=\"onDelete(key)\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n </div>\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"5\" class=\"text-center py-4 text-muted-color\">\n {{ 'localization.key.empty' | translate }}\n </td>\n </tr>\n </ng-template>\n </f-table>\n </div>\n `,\n})\nexport class TranslationKeyListPage implements OnInit {\n readonly TRANSLATION_KEY_PERMISSIONS = TRANSLATION_KEY_PERMISSIONS;\n\n private readonly router = inject(Router);\n private readonly languageService = inject(LanguageApiService);\n private readonly translationKeyService = inject(TranslationKeyApiService);\n private readonly translationService = inject(TranslationApiService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly messageService = inject(MessageService);\n private readonly translateService = inject(TranslateService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly isLoading = signal(false);\n readonly languages = signal<ILanguage[]>([]);\n readonly modules = signal<string[]>([]);\n readonly translationKeys = signal<ITranslationKey[]>([]);\n readonly translationCounts = signal<Map<string, number>>(new Map());\n readonly selectedModule = signal<string | null>(null);\n readonly searchTerm = signal('');\n private loadSeq = 0;\n private countsSeq = 0;\n\n readonly moduleOptions = computed(() => [\n { label: this.translateService.translate('shared.all'), value: null },\n ...this.modules().map((m) => ({ label: m, value: m })),\n ]);\n\n readonly filteredKeys = computed(() => {\n let keys = this.translationKeys();\n const module = this.selectedModule();\n const search = this.searchTerm().toLowerCase().trim();\n\n if (module) {\n keys = keys.filter((k) => k.module === module);\n }\n\n if (search) {\n keys = keys.filter(\n (k) =>\n k.key.toLowerCase().includes(search) ||\n k.defaultMessage.toLowerCase().includes(search) ||\n k.module.toLowerCase().includes(search),\n );\n }\n\n return keys;\n });\n\n ngOnInit(): void {\n this.loadData();\n }\n\n loadData(): void {\n const seq = ++this.loadSeq;\n this.isLoading.set(true);\n\n forkJoin({\n languages: from(\n this.languageService.getAll({\n pagination: { currentPage: 0, pageSize: 100 },\n filter: {},\n sort: { serial: 'ASC', name: 'ASC' },\n }),\n ),\n modules: this.translationKeyService.getModules(),\n keys: from(\n this.translationKeyService.getAll({\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: {},\n sort: { module: 'ASC', key: 'ASC' },\n }),\n ),\n })\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: ({ languages, modules, keys }) => {\n if (seq !== this.loadSeq) return;\n if (languages.success && languages.data) {\n this.languages.set(languages.data.filter((l) => l.isActive));\n }\n if (modules.success && modules.data) {\n this.modules.set(modules.data);\n }\n if (keys.success && keys.data) {\n this.translationKeys.set(keys.data);\n this.loadTranslationCounts();\n }\n this.isLoading.set(false);\n },\n error: () => {\n if (seq === this.loadSeq) this.isLoading.set(false);\n },\n });\n }\n\n loadTranslationCounts(): void {\n const seq = ++this.countsSeq;\n this.translationService\n .getCounts()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => {\n if (seq !== this.countsSeq) return;\n if (response.success && response.data) {\n this.translationCounts.set(new Map(Object.entries(response.data)));\n }\n },\n error: () => undefined,\n });\n }\n\n getTranslationCount(keyId: string): number {\n return this.translationCounts().get(keyId) ?? 0;\n }\n\n onModuleChange(value: string | null): void {\n this.selectedModule.set(value);\n }\n\n onCreate(): void {\n this.router.navigate(['/localization/keys/new']);\n }\n\n onEdit(key: ITranslationKey): void {\n this.router.navigate(['/localization/keys', key.id]);\n }\n\n onDelete(key: ITranslationKey): void {\n if (key.isReadonly) return;\n this.confirmationService.confirm({\n message: this.translateService.translate('shared.confirm.delete'),\n header: this.translateService.translate('localization.key.delete.title'),\n icon: 'exclamation-triangle',\n acceptButtonStyleClass: 'p-button-danger',\n accept: () => {\n from(this.translationKeyService.delete({ id: key.id, type: 'delete' }))\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe({\n next: (response) => {\n if (response.success) {\n this.messageService.add({\n severity: 'success',\n summary: this.translateService.translate('shared.success'),\n detail: response.messageKey\n ? this.translateService.translate(\n response.messageKey,\n response.messageVariables as Record<\n string,\n string | number\n >,\n )\n : (response.message ?? ''),\n });\n this.loadData();\n }\n },\n error: () => undefined,\n });\n },\n });\n }\n}\n"],"mappings":"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"}
@@ -210,7 +210,9 @@ var LocalizationInitializerService = class LocalizationInitializerService {
210
210
  if (!selectedLanguage && languagesResponse.data.length > 0) selectedLanguage = languagesResponse.data[0];
211
211
  if (selectedLanguage) this.stateService.setCurrentLanguage(selectedLanguage);
212
212
  }
213
- } catch (error) {} finally {
213
+ } catch {
214
+ return;
215
+ } finally {
214
216
  this.stateService.setLoading(false);
215
217
  }
216
218
  }
@@ -257,7 +259,11 @@ var LocalizationStateService = class LocalizationStateService {
257
259
  if (language && !this.platformService.isServer) {
258
260
  this.document.documentElement.dir = language.direction ?? "ltr";
259
261
  this.document.documentElement.lang = language.code;
260
- localStorage.setItem(STORAGE_KEYS.CURRENT_LANGUAGE, language.code);
262
+ try {
263
+ localStorage.setItem(STORAGE_KEYS.CURRENT_LANGUAGE, language.code);
264
+ } catch {
265
+ return;
266
+ }
261
267
  }
262
268
  });
263
269
  effect(() => {
@@ -285,7 +291,11 @@ var LocalizationStateService = class LocalizationStateService {
285
291
  }
286
292
  getSavedLanguageCode() {
287
293
  if (this.platformService.isServer) return null;
288
- return localStorage.getItem(STORAGE_KEYS.CURRENT_LANGUAGE);
294
+ try {
295
+ return localStorage.getItem(STORAGE_KEYS.CURRENT_LANGUAGE);
296
+ } catch {
297
+ return null;
298
+ }
289
299
  }
290
300
  isModuleLoaded(module) {
291
301
  return this._loadedModules.has(module);
@@ -406,35 +416,48 @@ var TranslationLoaderService = class TranslationLoaderService {
406
416
  config = inject(LOCALIZATION_CONFIG, { optional: true });
407
417
  apiService = inject(LOCALIZATION_API_SERVICE, { optional: false });
408
418
  stateService = inject(LOCALIZATION_STATE_SERVICE, { optional: false });
419
+ loadToken = 0;
420
+ pendingReloadModules = [];
409
421
  async loadTranslations(languageCode, clearModules = false) {
422
+ const token = ++this.loadToken;
423
+ const isCurrent = () => token === this.loadToken;
410
424
  const strategy = this.config?.loadStrategy ?? "all";
411
- const previouslyLoadedModules = clearModules ? this.stateService.getLoadedModules() : [];
412
- if (clearModules) this.stateService.clearLoadedModules();
425
+ let previouslyLoadedModules = [];
426
+ if (clearModules) {
427
+ previouslyLoadedModules = Array.from(/* @__PURE__ */ new Set([...this.pendingReloadModules, ...this.stateService.getLoadedModules()]));
428
+ this.pendingReloadModules = previouslyLoadedModules;
429
+ this.stateService.clearLoadedModules();
430
+ }
413
431
  this.stateService.setLoading(true);
414
432
  try {
415
- if (strategy === "all") await this.loadAndSetTranslations(languageCode);
433
+ if (strategy === "all") await this.loadAndSetTranslations(languageCode, void 0, isCurrent);
416
434
  else {
417
435
  const modules = this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;
418
- await this.loadAndSetTranslations(languageCode, modules);
419
- if (previouslyLoadedModules.length > 0) await this.reloadModules(languageCode, previouslyLoadedModules);
436
+ await this.loadAndSetTranslations(languageCode, modules, isCurrent);
437
+ if (isCurrent() && previouslyLoadedModules.length > 0) await this.reloadModules(languageCode, previouslyLoadedModules, isCurrent);
420
438
  }
439
+ } catch {
440
+ return;
421
441
  } finally {
422
- this.stateService.setLoading(false);
442
+ if (isCurrent()) {
443
+ this.pendingReloadModules = [];
444
+ this.stateService.setLoading(false);
445
+ }
423
446
  }
424
447
  }
425
- async loadAndSetTranslations(languageCode, modules) {
448
+ async loadAndSetTranslations(languageCode, modules, isCurrent) {
426
449
  const response = await firstValueFrom(this.apiService.getTranslationsByLanguage(languageCode, modules));
427
- if (response.success && response.data) {
450
+ if (isCurrent() && response?.success && response.data) {
428
451
  this.stateService.setTranslations(response.data);
429
452
  if (modules) modules.forEach((m) => this.stateService.markModuleLoaded(m));
430
453
  }
431
454
  }
432
- async reloadModules(languageCode, modules) {
455
+ async reloadModules(languageCode, modules, isCurrent) {
433
456
  const initialModules = this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;
434
457
  const additionalModules = modules.filter((m) => !initialModules.includes(m));
435
458
  if (additionalModules.length === 0) return;
436
459
  const response = await firstValueFrom(this.apiService.getTranslationsByLanguage(languageCode, additionalModules));
437
- if (response.success && response.data) {
460
+ if (isCurrent() && response?.success && response.data) {
438
461
  this.stateService.mergeTranslations(response.data);
439
462
  additionalModules.forEach((m) => this.stateService.markModuleLoaded(m));
440
463
  }
@@ -718,17 +741,17 @@ const LOCALIZATION_ROUTES = [{
718
741
  children: [
719
742
  {
720
743
  path: "",
721
- loadComponent: () => import("./flusys-ng-localization-language-list.page-B8wnYNNd.mjs").then((m) => m.LanguageListPage)
744
+ loadComponent: () => import("./flusys-ng-localization-language-list.page-CfM-mc9g.mjs").then((m) => m.LanguageListPage)
722
745
  },
723
746
  {
724
747
  path: "new",
725
748
  canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.CREATE)],
726
- loadComponent: () => import("./flusys-ng-localization-language-form.page-BdxZ6meb.mjs").then((m) => m.LanguageFormPage)
749
+ loadComponent: () => import("./flusys-ng-localization-language-form.page-DB-cn7MO.mjs").then((m) => m.LanguageFormPage)
727
750
  },
728
751
  {
729
752
  path: ":id",
730
753
  canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.UPDATE)],
731
- loadComponent: () => import("./flusys-ng-localization-language-form.page-BdxZ6meb.mjs").then((m) => m.LanguageFormPage)
754
+ loadComponent: () => import("./flusys-ng-localization-language-form.page-DB-cn7MO.mjs").then((m) => m.LanguageFormPage)
732
755
  }
733
756
  ]
734
757
  },
@@ -738,17 +761,17 @@ const LOCALIZATION_ROUTES = [{
738
761
  children: [
739
762
  {
740
763
  path: "",
741
- loadComponent: () => import("./flusys-ng-localization-translation-key-list.page-DhRI5UvT.mjs").then((m) => m.TranslationKeyListPage)
764
+ loadComponent: () => import("./flusys-ng-localization-translation-key-list.page-CGC5125Z.mjs").then((m) => m.TranslationKeyListPage)
742
765
  },
743
766
  {
744
767
  path: "new",
745
768
  canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.CREATE)],
746
- loadComponent: () => import("./flusys-ng-localization-translation-key-form.page-Dgn58Sh7.mjs").then((m) => m.TranslationKeyFormPage)
769
+ loadComponent: () => import("./flusys-ng-localization-translation-key-form.page-BCkDs0tt.mjs").then((m) => m.TranslationKeyFormPage)
747
770
  },
748
771
  {
749
772
  path: ":id",
750
773
  canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.UPDATE)],
751
- loadComponent: () => import("./flusys-ng-localization-translation-key-form.page-Dgn58Sh7.mjs").then((m) => m.TranslationKeyFormPage)
774
+ loadComponent: () => import("./flusys-ng-localization-translation-key-form.page-BCkDs0tt.mjs").then((m) => m.TranslationKeyFormPage)
752
775
  }
753
776
  ]
754
777
  },
@@ -1 +1 @@
1
- {"version":3,"file":"flusys-ng-localization.mjs","names":[],"sources":["../../../projects/ng-localization/interfaces/localization-config.interface.ts","../../../projects/ng-localization/constants/localization.constants.ts","../../../projects/ng-localization/constants/messages.ts","../../../projects/ng-localization/services/language-api.service.ts","../../../projects/ng-localization/services/localization-api.service.ts","../../../projects/ng-localization/services/localization-initializer.service.ts","../../../projects/ng-localization/services/localization-state.service.ts","../../../projects/ng-localization/services/translation-api.service.ts","../../../projects/ng-localization/services/translation-key-api.service.ts","../../../projects/ng-localization/services/translation-loader.service.ts","../../../projects/ng-localization/components/language-selector/language-selector.component.ts","../../../projects/ng-localization/components/language-selector-panel/language-selector-panel.component.ts","../../../projects/ng-localization/providers/localization.providers.ts","../../../projects/ng-localization/routes/localization.routes.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport type LocalizationLoadStrategy = 'all' | 'modules';\n\n/** Localization system configuration */\nexport interface ILocalizationConfig {\n /** Default language code (e.g., 'en', 'ar') */\n defaultLanguageCode: string;\n /** Translation loading strategy (default: 'modules') */\n loadStrategy?: LocalizationLoadStrategy;\n /** Modules to load at app initialization (default: []) */\n initialModules?: string[];\n /** Show language selector in layout (default: false) */\n enableLayoutSelector?: boolean;\n}\n\nexport const LOCALIZATION_CONFIG = new InjectionToken<ILocalizationConfig>(\n 'LOCALIZATION_CONFIG',\n);\n\n/** Get localization config with sensible defaults applied */\nexport function getLocalizationConfig(\n overrides?: Partial<ILocalizationConfig>,\n): ILocalizationConfig {\n const defaults: ILocalizationConfig = {\n defaultLanguageCode: 'en',\n loadStrategy: 'all',\n initialModules: [],\n enableLayoutSelector: false,\n };\n\n return {\n ...defaults,\n ...overrides,\n defaultLanguageCode:\n overrides?.defaultLanguageCode || defaults.defaultLanguageCode,\n };\n}\n","export const STORAGE_KEYS = {\n CURRENT_LANGUAGE: 'flusys.language',\n} as const;\n","export const LOCALIZATION_MESSAGES: Record<string, string> = {\n // Language CRUD (API keys)\n 'language.create.success': 'Language created successfully',\n 'language.create.many.success': '{{count}} languages created successfully',\n 'language.get.success': 'Language retrieved successfully',\n 'language.get.by.ids.success': 'Languages retrieved successfully by Ids',\n 'language.get.by.filter.success':\n 'Languages retrieved successfully by filter',\n 'language.get.all.success': 'Languages retrieved successfully',\n 'language.update.success': 'Language updated successfully',\n 'language.update.many.success': '{{count}} languages updated successfully',\n 'language.delete.success': 'Language deleted successfully',\n 'language.restore.success': 'Language restored successfully',\n 'language.readonly.update.forbidden':\n 'Cannot modify code/name of readonly language \"{{name}}\"',\n 'language.readonly.delete.forbidden': 'Cannot delete readonly language(s): {{names}}',\n 'language.default.delete.forbidden':\n 'Cannot delete the default language(s): {{names}}. Set another language as default first.',\n 'language.active.success': 'Active languages retrieved successfully',\n 'language.set.default.success': 'Default language updated successfully',\n 'language.get.default.success': 'Default language retrieved successfully',\n\n // Translation key CRUD (API keys)\n 'translation.key.create.success': 'Translation key created successfully',\n 'translation.key.create.many.success':\n '{{count}} translation keys created successfully',\n 'translation.key.get.success': 'Translation key retrieved successfully',\n 'translation.key.get.by.ids.success':\n 'Translation keys retrieved successfully by Ids',\n 'translation.key.get.by.filter.success':\n 'Translation keys retrieved successfully by filter',\n 'translation.key.get.all.success': 'Translation keys retrieved successfully',\n 'translation.key.update.success': 'Translation key updated successfully',\n 'translation.key.update.many.success':\n '{{count}} translation keys updated successfully',\n 'translation.key.delete.success': 'Translation key deleted successfully',\n 'translation.key.restore.success': 'Translation key restored successfully',\n 'translation.key.modules.success': 'Modules retrieved successfully',\n 'translation.key.readonly.delete.forbidden':\n 'Cannot delete readonly translation keys: {{keys}}',\n 'translation.key.readonly.update.forbidden':\n 'Cannot modify key or module of system translation keys',\n 'translation.key.duplicate.key.in.module':\n 'Translation key \"{{key}}\" already exists in module \"{{module}}\"',\n\n // Translation CRUD (API keys)\n 'translation.create.success': 'Translation created successfully',\n 'translation.create.many.success':\n '{{count}} translations created successfully',\n 'translation.get.success': 'Translation retrieved successfully',\n 'translation.get.by.ids.success':\n 'Translations retrieved successfully by Ids',\n 'translation.get.by.filter.success':\n 'Translations retrieved successfully by filter',\n 'translation.get.all.success': 'Translations retrieved successfully',\n 'translation.update.success': 'Translation updated successfully',\n 'translation.update.many.success':\n '{{count}} translations updated successfully',\n 'translation.delete.success': 'Translation deleted successfully',\n 'translation.restore.success': 'Translation restored successfully',\n 'translation.by.language.success': 'Translations retrieved successfully',\n\n // pages/localization-container/localization-container.page.ts\n 'localization.title': 'Localization',\n 'localization.subtitle': 'Manage languages and translations',\n 'localization.tabs.languages': 'Languages',\n 'localization.tabs.keys': 'Keys',\n\n // pages/language-list/language-list.page.ts\n 'localization.language.title': 'Languages',\n 'localization.language.subtitle':\n 'Manage available languages for your application',\n 'localization.language.new': 'Add Language',\n 'localization.language.code': 'Language Code',\n 'localization.language.name': 'Language Name',\n 'localization.language.native.name': 'Native Name',\n 'localization.language.direction': 'Text Direction',\n 'localization.language.rtl': 'RTL',\n 'localization.language.ltr': 'LTR',\n 'localization.language.default': 'Default',\n 'localization.language.set.default': 'Set as Default',\n 'localization.language.empty':\n 'No languages configured. Add a language to get started.',\n 'localization.language.confirm.set.default':\n 'Set \"{{name}}\" as the default language?',\n 'localization.language.delete.title': 'Delete Language',\n 'localization.language.default.delete.forbidden':\n 'Cannot delete the default language. Set another language as default first.',\n 'localization.language.readonly.delete.forbidden':\n 'This is a system language and cannot be deleted',\n\n // pages/language-form/language-form.page.ts\n 'localization.language.edit': 'Edit Language',\n 'localization.language.readonly.edit.hint':\n 'This is a system language — its code, name, native name, and direction cannot be changed',\n 'localization.placeholder.code': 'en',\n 'localization.language.iso.code.hint':\n 'ISO 639-1 language code (e.g., en, ar, fr)',\n 'localization.placeholder.name': 'English',\n 'localization.placeholder.native.name': 'English',\n 'localization.language.native.name.hint':\n 'Name in the native language (e.g., العربية for Arabic)',\n 'localization.language.display.order': 'Display Order',\n 'localization.language.direction.ltr': 'Left to Right (LTR)',\n 'localization.language.direction.rtl': 'Right to Left (RTL)',\n 'localization.validation.code.required': 'Language code is required',\n 'localization.validation.code.max.length':\n 'Language code must be at most 10 characters',\n 'localization.validation.name.required': 'Language name is required',\n 'localization.validation.name.max.length':\n 'Language name must be at most 100 characters',\n\n // pages/translation-key-list/translation-key-list.page.ts\n 'localization.key.title': 'Translation Keys',\n 'localization.key.subtitle': 'Manage translation keys for your application',\n 'localization.key.new': 'Add Key',\n 'localization.key.filter.module': 'Filter by module',\n 'localization.key.module': 'Module',\n 'localization.key.name': 'Key Name',\n 'localization.key.default.message': 'Default Message',\n 'localization.key.translations': 'Translations',\n 'localization.key.empty': 'No translation keys found',\n 'localization.key.delete.title': 'Delete Translation Key',\n 'localization.key.readonly.delete.forbidden':\n 'This is a system translation key and cannot be deleted',\n 'localization.key.readonly.edit.hint':\n 'This is a system key — its key name and module cannot be changed',\n\n // pages/translation-key-form/translation-key-form.page.ts\n 'localization.key.edit': 'Edit Key',\n 'localization.key.about': 'Key Information',\n 'localization.placeholder.key.name': 'button.submit',\n 'localization.key.select.module': 'Select or enter module',\n 'localization.placeholder.default.message': 'Enter default value (English)',\n 'localization.key.description': 'Description',\n 'localization.placeholder.key.description':\n 'Optional description for translators',\n 'localization.key.variables': 'Variables',\n 'localization.key.variables.placeholder': 'e.g., name, count, date',\n 'localization.key.variables.hint':\n 'Enter variable names used in this translation',\n 'localization.key.translations.section': 'Translations',\n 'localization.key.no.languages': 'No active languages configured',\n 'localization.key.enter.translation': 'Enter translation',\n 'localization.validation.key.required': 'Translation key is required',\n 'localization.validation.default.message.required':\n 'Default message is required',\n};\n","import { Service } from '@angular/core';\nimport { ApiResourceService, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateLanguageDto,\n ILanguage,\n IUpdateLanguageDto,\n} from '../interfaces/language.interface';\n\n@Service()\nexport class LanguageApiService extends ApiResourceService<\n ICreateLanguageDto | IUpdateLanguageDto,\n ILanguage\n> {\n constructor() {\n super('language', 'localization');\n }\n\n setDefault(id: string): Observable<ISingleResponse<ILanguage>> {\n return this.http.post<ISingleResponse<ILanguage>>(\n `${this.baseUrl}/set-default`,\n { id },\n );\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { IListResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { ILanguage, ITranslationsMap } from '../interfaces/language.interface';\n\n@Service()\nexport class LocalizationApiService {\n private readonly http = inject(HttpClient);\n private readonly appConfig = inject(APP_CONFIG);\n\n private get baseUrl(): string {\n return `${this.appConfig.apiBaseUrl}/localization`;\n }\n\n getActiveLanguages(): Observable<IListResponse<ILanguage>> {\n return this.http.post<IListResponse<ILanguage>>(`${this.baseUrl}/language/get-active`, {});\n }\n\n getTranslationsByLanguage(languageCode: string, modules?: string[]): Observable<ISingleResponse<ITranslationsMap>> {\n return this.http.post<ISingleResponse<ITranslationsMap>>(\n `${this.baseUrl}/translation/get-by-language`,\n { languageCode, ...(modules?.length ? { modules } : {}) },\n );\n }\n}\n","import { inject, Service } from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport { firstValueFrom } from 'rxjs';\nimport { LocalizationApiService } from './localization-api.service';\nimport { LocalizationStateService } from './localization-state.service';\n\n@Service()\nexport class LocalizationInitializerService {\n apiService: LocalizationApiService = inject(LOCALIZATION_API_SERVICE, {\n optional: false,\n }) as LocalizationApiService;\n\n stateService: LocalizationStateService = inject(LOCALIZATION_STATE_SERVICE, {\n optional: false,\n }) as unknown as LocalizationStateService;\n\n async initialize(\n initialFallbackMessages?: Record<string, string>,\n ): Promise<void> {\n try {\n this.stateService.setLoading(true);\n if (initialFallbackMessages) {\n this.stateService.updateFallbackMessages(initialFallbackMessages);\n }\n const languagesResponse = await firstValueFrom(\n this.apiService.getActiveLanguages(),\n );\n if (languagesResponse.success && languagesResponse.data) {\n this.stateService.setAvailableLanguages(languagesResponse.data);\n\n const savedCode = this.stateService.getSavedLanguageCode();\n let selectedLanguage = languagesResponse.data.find(\n (l) => l.code === savedCode,\n );\n\n if (!selectedLanguage) {\n selectedLanguage = languagesResponse.data.find((l) => l.isDefault);\n }\n\n if (!selectedLanguage && languagesResponse.data.length > 0) {\n selectedLanguage = languagesResponse.data[0];\n }\n\n if (selectedLanguage) {\n this.stateService.setCurrentLanguage(selectedLanguage);\n }\n }\n } catch (error) {\n // Silently fail - use default language\n } finally {\n this.stateService.setLoading(false);\n }\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport { ApplicationRef, computed, effect, inject, signal, Service } from '@angular/core';\nimport { PlatformService } from '@flusys/ng-shared';\nimport { STORAGE_KEYS } from '../constants/localization.constants';\nimport { ILanguage, ITranslationsMap } from '../interfaces/language.interface';\n\n@Service()\nexport class LocalizationStateService {\n private readonly platformService = inject(PlatformService);\n private readonly document = inject(DOCUMENT);\n private readonly appRef = inject(ApplicationRef);\n private readonly _loadedModules = new Set<string>();\n private readonly _currentLanguage = signal<ILanguage | null>(null);\n private readonly _availableLanguages = signal<ILanguage[]>([]);\n private readonly _translations = signal<ITranslationsMap>({});\n private readonly _fallbackMessages = signal<ITranslationsMap>({});\n private readonly _isLoading = signal<boolean>(false);\n\n readonly availableLanguages = this._availableLanguages.asReadonly();\n readonly translations = this._translations.asReadonly();\n readonly fallbackMessages = this._fallbackMessages.asReadonly();\n readonly isLoading = this._isLoading.asReadonly();\n\n readonly currentLanguageCode = computed(\n () => this._currentLanguage()?.code ?? 'en',\n );\n\n constructor() {\n effect(() => {\n const language = this._currentLanguage();\n if (language && !this.platformService.isServer) {\n this.document.documentElement.dir = language.direction ?? 'ltr';\n this.document.documentElement.lang = language.code;\n localStorage.setItem(STORAGE_KEYS.CURRENT_LANGUAGE, language.code);\n }\n });\n\n effect(() => {\n this._translations();\n setTimeout(() => this.appRef.tick(), 0);\n });\n }\n\n setCurrentLanguage(language: ILanguage): void {\n this._currentLanguage.set(language);\n }\n\n setAvailableLanguages(languages: ILanguage[]): void {\n this._availableLanguages.set(languages);\n }\n\n setTranslations(translations: ITranslationsMap): void {\n this._translations.set(translations);\n }\n\n mergeTranslations(translations: ITranslationsMap): void {\n this._translations.update((current) => ({ ...current, ...translations }));\n }\n\n setLoading(loading: boolean): void {\n this._isLoading.set(loading);\n }\n\n getSavedLanguageCode(): string | null {\n if (this.platformService.isServer) return null;\n return localStorage.getItem(STORAGE_KEYS.CURRENT_LANGUAGE);\n }\n\n isModuleLoaded(module: string): boolean {\n return this._loadedModules.has(module);\n }\n\n markModuleLoaded(module: string): void {\n this._loadedModules.add(module);\n }\n\n getLoadedModules(): string[] {\n return Array.from(this._loadedModules);\n }\n\n clearLoadedModules(): void {\n this._loadedModules.clear();\n }\n\n updateFallbackMessages(messages: ITranslationsMap): void {\n this._fallbackMessages.update((current) => ({ ...current, ...messages }));\n }\n}\n","import { Service } from '@angular/core';\nimport {\n ApiResourceService,\n IListResponse,\n ISingleResponse,\n} from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { ITranslation } from '../interfaces/translation.interface';\n\nexport interface ICreateTranslationDto {\n languageId: string;\n translationKeyId: string;\n value: string;\n isVerified?: boolean;\n isActive?: boolean;\n}\n\nexport interface IUpdateTranslationDto extends Partial<ICreateTranslationDto> {\n id: string;\n}\n\nexport interface IBulkUpdateTranslationDto {\n id?: string;\n languageId: string;\n translationKeyId: string;\n value: string;\n isVerified?: boolean;\n}\n\n@Service()\nexport class TranslationApiService extends ApiResourceService<\n ICreateTranslationDto | IUpdateTranslationDto,\n ITranslation\n> {\n constructor() {\n super('translation', 'localization');\n }\n\n getByKeyId(\n translationKeyId: string,\n ): Observable<IListResponse<ITranslation>> {\n return this.http.post<IListResponse<ITranslation>>(\n `${this.baseUrl}/get-all`,\n {\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: { translationKeyId },\n sort: {},\n },\n );\n }\n\n getCounts(): Observable<ISingleResponse<Record<string, number>>> {\n return this.http.post<ISingleResponse<Record<string, number>>>(\n `${this.baseUrl}/get-counts`,\n {},\n );\n }\n\n bulkUpdate(\n translations: IBulkUpdateTranslationDto[],\n ): Observable<IListResponse<ITranslation>> {\n return this.http.post<IListResponse<ITranslation>>(\n `${this.baseUrl}/update-many-values`,\n { translations },\n );\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateTranslationKeyDto,\n ITranslationKey,\n IUpdateTranslationKeyDto,\n} from '../interfaces/translation-key.interface';\n\n@Service()\nexport class TranslationKeyApiService extends ApiResourceService<\n ICreateTranslationKeyDto | IUpdateTranslationKeyDto,\n ITranslationKey\n> {\n constructor() {\n super('translation-key', 'localization');\n }\n\n getModules(): Observable<ISingleResponse<string[]>> {\n return this.http.post<ISingleResponse<string[]>>(\n `${this.baseUrl}/get-modules`,\n {},\n );\n }\n}\n","import { inject, Service } from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport { firstValueFrom, from, Observable } from 'rxjs';\nimport { LOCALIZATION_CONFIG } from '../interfaces/localization-config.interface';\nimport { LocalizationApiService } from './localization-api.service';\nimport { LocalizationStateService } from './localization-state.service';\n\n@Service()\nexport class TranslationLoaderService {\n private readonly DEFAULT_INITIAL_MODULES = ['shared', 'layout'];\n private readonly config = inject(LOCALIZATION_CONFIG, { optional: true });\n apiService: LocalizationApiService = inject(LOCALIZATION_API_SERVICE, {\n optional: false,\n }) as LocalizationApiService;\n\n stateService: LocalizationStateService = inject(LOCALIZATION_STATE_SERVICE, {\n optional: false,\n }) as unknown as LocalizationStateService;\n\n async loadTranslations(\n languageCode: string,\n clearModules = false,\n ): Promise<void> {\n const strategy = this.config?.loadStrategy ?? 'all';\n\n // Save currently loaded modules before clearing (for language switch)\n const previouslyLoadedModules = clearModules\n ? this.stateService.getLoadedModules()\n : [];\n\n if (clearModules) {\n this.stateService.clearLoadedModules();\n }\n\n this.stateService.setLoading(true);\n\n try {\n if (strategy === 'all') {\n await this.loadAndSetTranslations(languageCode);\n } else {\n const modules =\n this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;\n await this.loadAndSetTranslations(languageCode, modules);\n // Reload all previously loaded modules for the new language\n if (previouslyLoadedModules.length > 0) {\n await this.reloadModules(languageCode, previouslyLoadedModules);\n }\n }\n } finally {\n this.stateService.setLoading(false);\n }\n }\n\n private async loadAndSetTranslations(\n languageCode: string,\n modules?: string[],\n ): Promise<void> {\n const response = await firstValueFrom(\n this.apiService.getTranslationsByLanguage(languageCode, modules),\n );\n if (response.success && response.data) {\n this.stateService.setTranslations(response.data);\n if (modules) {\n modules.forEach((m) => this.stateService.markModuleLoaded(m));\n }\n }\n }\n\n private async reloadModules(\n languageCode: string,\n modules: string[],\n ): Promise<void> {\n const initialModules =\n this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;\n const additionalModules = modules.filter(\n (m) => !initialModules.includes(m),\n );\n\n if (additionalModules.length === 0) return;\n\n const response = await firstValueFrom(\n this.apiService.getTranslationsByLanguage(\n languageCode,\n additionalModules,\n ),\n );\n\n if (response.success && response.data) {\n this.stateService.mergeTranslations(response.data);\n additionalModules.forEach((m) => this.stateService.markModuleLoaded(m));\n }\n }\n\n loadTranslationsAsync(\n languageCode: string,\n clearModules = false,\n ): Observable<void> {\n return from(this.loadTranslations(languageCode, clearModules));\n }\n}\n","import { Component, DestroyRef, computed, inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MenuComponent, MenuItem, UiIconComponent } from '@flusys/ng-ui';\nimport { LocalizationStateService } from '../../services/localization-state.service';\nimport { TranslationLoaderService } from '../../services/translation-loader.service';\n\n@Component({\n selector: 'lib-language-selector',\n imports: [MenuComponent, UiIconComponent],\n host: { class: 'relative' },\n template: `\n <button\n type=\"button\"\n class=\"layout-topbar-action\"\n [class.layout-topbar-action-highlight]=\"menu.visible()\"\n (click)=\"menu.toggle($event)\"\n >\n <ui-icon name=\"globe\"></ui-icon>\n <span class=\"font-semibold\">{{\n selectedLanguage()?.nativeName ||\n selectedLanguage()?.name ||\n selectedLanguageCode()\n }}</span>\n </button>\n <f-menu\n #menu\n [model]=\"menuItems()\"\n [popup]=\"true\"\n class=\"absolute left-[0]\"\n [style]=\"{ 'inset-inline-end': '0' }\"\n />\n `,\n})\nexport class LanguageSelectorComponent {\n private readonly localizationState = inject(LocalizationStateService);\n private readonly translationLoader = inject(TranslationLoaderService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly languages = this.localizationState.availableLanguages;\n\n readonly selectedLanguageCode = this.localizationState.currentLanguageCode;\n readonly selectedLanguage = computed(\n () =>\n this.languages().find((l) => l.code === this.selectedLanguageCode()) ??\n null,\n );\n\n readonly menuItems = computed<MenuItem[]>(() =>\n this.languages().map((lang) => ({\n label: lang.nativeName || lang.name,\n badge: lang.code.toUpperCase(),\n selected: lang.code === this.selectedLanguageCode(),\n command: () => this.onLanguageSelect(lang.code),\n })),\n );\n\n onLanguageSelect(code: string): void {\n const language = this.languages().find((l) => l.code === code);\n if (language) {\n this.localizationState.setCurrentLanguage(language);\n this.translationLoader\n .loadTranslationsAsync(code, true)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe();\n }\n }\n}\n","import {\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MenuComponent, MenuItem } from '@flusys/ng-ui';\nimport { LocalizationStateService } from '../../services/localization-state.service';\nimport { TranslationLoaderService } from '../../services/translation-loader.service';\n\n@Component({\n selector: 'lib-language-selector-panel',\n imports: [MenuComponent],\n host: {\n class: 'hidden absolute z-50 top-[24px] p-3 min-w-[180px]',\n style: 'inset-inline-end: 0;',\n },\n template: `<f-menu [model]=\"menuItems()\" />`,\n})\nexport class LanguageSelectorPanelComponent {\n private readonly localizationState = inject(LocalizationStateService);\n private readonly translationLoader = inject(TranslationLoaderService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly languages = this.localizationState.availableLanguages;\n\n private readonly _selectedLanguageCode = signal<string>(\n this.localizationState.currentLanguageCode(),\n );\n readonly selectedLanguageCode = this._selectedLanguageCode.asReadonly();\n\n readonly menuItems = computed<MenuItem[]>(() =>\n this.languages().map((lang) => ({\n label: lang.nativeName || lang.name,\n badge: lang.code.toUpperCase(),\n selected: lang.code === this.selectedLanguageCode(),\n command: () => this.onLanguageSelect(lang.code),\n })),\n );\n\n constructor() {\n effect(() => {\n const currentCode = this.localizationState.currentLanguageCode();\n if (currentCode !== this._selectedLanguageCode()) {\n this._selectedLanguageCode.set(currentCode);\n }\n });\n }\n\n onLanguageSelect(code: string): void {\n const language = this.languages().find((l) => l.code === code);\n if (language) {\n this._selectedLanguageCode.set(code);\n this.localizationState.setCurrentLanguage(language);\n this.translationLoader\n .loadTranslationsAsync(code, true)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe();\n }\n }\n}\n","import {\n EnvironmentProviders,\n inject,\n provideAppInitializer,\n Provider,\n} from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport {\n LAYOUT_LANGUAGE_SELECTOR,\n LAYOUT_LANGUAGE_SELECTOR_PANEL,\n} from '@flusys/ng-layout';\nimport { LanguageSelectorPanelComponent } from '../components/language-selector-panel/language-selector-panel.component';\nimport { LanguageSelectorComponent } from '../components/language-selector/language-selector.component';\nimport {\n ILocalizationConfig,\n LOCALIZATION_CONFIG,\n} from '../interfaces/localization-config.interface';\nimport { LocalizationApiService } from '../services/localization-api.service';\nimport { LocalizationInitializerService } from '../services/localization-initializer.service';\nimport { LocalizationStateService } from '../services/localization-state.service';\n\nexport function provideLocalization(\n config: ILocalizationConfig,\n initialFallbackMessages?: Record<string, string>,\n): Array<Provider | EnvironmentProviders> {\n const providers: Array<Provider | EnvironmentProviders> = [\n // 1. Value/Existing Providers\n { provide: LOCALIZATION_CONFIG, useValue: config },\n {\n provide: LOCALIZATION_STATE_SERVICE,\n useExisting: LocalizationStateService,\n },\n { provide: LOCALIZATION_API_SERVICE, useExisting: LocalizationApiService },\n\n // 2. The Service itself\n LocalizationInitializerService,\n\n // 3. The modern Initializer\n provideAppInitializer(() => {\n const initializer = inject(LocalizationInitializerService);\n return initializer.initialize(initialFallbackMessages);\n }),\n ];\n\n if (config.enableLayoutSelector) {\n providers.push(\n {\n provide: LAYOUT_LANGUAGE_SELECTOR,\n useValue: LanguageSelectorComponent,\n },\n {\n provide: LAYOUT_LANGUAGE_SELECTOR_PANEL,\n useValue: LanguageSelectorPanelComponent,\n },\n );\n }\n\n return providers;\n}\n","import { inject } from '@angular/core';\nimport { Routes } from '@angular/router';\nimport {\n LANGUAGE_PERMISSIONS,\n PermissionValidatorService,\n permissionGuard,\n SHARED_MESSAGES,\n resolveTranslationModule,\n TRANSLATION_KEY_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { LOCALIZATION_MESSAGES } from '../constants/messages';\n\n/**\n * Resolves which localization tab the current user should land on when\n * navigating to the bare `/localization` route. Mirrors the tab\n * visibility order in LocalizationContainerPage.visibleTabs so the\n * redirect never points at a tab the user can't actually see.\n */\nfunction resolveLocalizationDefaultTab(): string {\n const permissionValidator = inject(PermissionValidatorService);\n\n if (permissionValidator.hasPermission(LANGUAGE_PERMISSIONS.READ)) {\n return 'languages';\n }\n\n if (permissionValidator.hasPermission(TRANSLATION_KEY_PERMISSIONS.READ)) {\n return 'keys';\n }\n\n return 'languages';\n}\n\nexport const LOCALIZATION_ROUTES: Routes = [\n {\n path: '',\n resolve: { translations: resolveTranslationModule({ modules: ['localization'], fallbackMessages: { ...LOCALIZATION_MESSAGES, ...SHARED_MESSAGES } }) },\n loadComponent: () =>\n import('../pages/localization-container/localization-container.page').then(\n (m) => m.LocalizationContainerPage,\n ),\n children: [\n // Languages Management\n {\n path: 'languages',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/language-list/language-list.page').then((m) => m.LanguageListPage),\n },\n {\n path: 'new',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.CREATE)],\n loadComponent: () =>\n import('../pages/language-form/language-form.page').then((m) => m.LanguageFormPage),\n },\n {\n path: ':id',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.UPDATE)],\n loadComponent: () =>\n import('../pages/language-form/language-form.page').then((m) => m.LanguageFormPage),\n },\n ],\n },\n\n // Translation Keys Management\n {\n path: 'keys',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/translation-key-list/translation-key-list.page').then(\n (m) => m.TranslationKeyListPage,\n ),\n },\n {\n path: 'new',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.CREATE)],\n loadComponent: () =>\n import('../pages/translation-key-form/translation-key-form.page').then(\n (m) => m.TranslationKeyFormPage,\n ),\n },\n {\n path: ':id',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.UPDATE)],\n loadComponent: () =>\n import('../pages/translation-key-form/translation-key-form.page').then(\n (m) => m.TranslationKeyFormPage,\n ),\n },\n ],\n },\n\n // Default redirect to the first tab the user has permission to see\n {\n path: '',\n redirectTo: () => resolveLocalizationDefaultTab(),\n pathMatch: 'full',\n },\n ],\n },\n];\n"],"mappings":"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"}
1
+ {"version":3,"file":"flusys-ng-localization.mjs","names":[],"sources":["../../../projects/ng-localization/interfaces/localization-config.interface.ts","../../../projects/ng-localization/constants/localization.constants.ts","../../../projects/ng-localization/constants/messages.ts","../../../projects/ng-localization/services/language-api.service.ts","../../../projects/ng-localization/services/localization-api.service.ts","../../../projects/ng-localization/services/localization-initializer.service.ts","../../../projects/ng-localization/services/localization-state.service.ts","../../../projects/ng-localization/services/translation-api.service.ts","../../../projects/ng-localization/services/translation-key-api.service.ts","../../../projects/ng-localization/services/translation-loader.service.ts","../../../projects/ng-localization/components/language-selector/language-selector.component.ts","../../../projects/ng-localization/components/language-selector-panel/language-selector-panel.component.ts","../../../projects/ng-localization/providers/localization.providers.ts","../../../projects/ng-localization/routes/localization.routes.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\nexport type LocalizationLoadStrategy = 'all' | 'modules';\n\n/** Localization system configuration */\nexport interface ILocalizationConfig {\n /** Default language code (e.g., 'en', 'ar') */\n defaultLanguageCode: string;\n /** Translation loading strategy (default: 'modules') */\n loadStrategy?: LocalizationLoadStrategy;\n /** Modules to load at app initialization (default: []) */\n initialModules?: string[];\n /** Show language selector in layout (default: false) */\n enableLayoutSelector?: boolean;\n}\n\nexport const LOCALIZATION_CONFIG = new InjectionToken<ILocalizationConfig>(\n 'LOCALIZATION_CONFIG',\n);\n\n/** Get localization config with sensible defaults applied */\nexport function getLocalizationConfig(\n overrides?: Partial<ILocalizationConfig>,\n): ILocalizationConfig {\n const defaults: ILocalizationConfig = {\n defaultLanguageCode: 'en',\n loadStrategy: 'all',\n initialModules: [],\n enableLayoutSelector: false,\n };\n\n return {\n ...defaults,\n ...overrides,\n defaultLanguageCode:\n overrides?.defaultLanguageCode || defaults.defaultLanguageCode,\n };\n}\n","export const STORAGE_KEYS = {\n CURRENT_LANGUAGE: 'flusys.language',\n} as const;\n","export const LOCALIZATION_MESSAGES: Record<string, string> = {\n // Language CRUD (API keys)\n 'language.create.success': 'Language created successfully',\n 'language.create.many.success': '{{count}} languages created successfully',\n 'language.get.success': 'Language retrieved successfully',\n 'language.get.by.ids.success': 'Languages retrieved successfully by Ids',\n 'language.get.by.filter.success':\n 'Languages retrieved successfully by filter',\n 'language.get.all.success': 'Languages retrieved successfully',\n 'language.update.success': 'Language updated successfully',\n 'language.update.many.success': '{{count}} languages updated successfully',\n 'language.delete.success': 'Language deleted successfully',\n 'language.restore.success': 'Language restored successfully',\n 'language.readonly.update.forbidden':\n 'Cannot modify code/name of readonly language \"{{name}}\"',\n 'language.readonly.delete.forbidden': 'Cannot delete readonly language(s): {{names}}',\n 'language.default.delete.forbidden':\n 'Cannot delete the default language(s): {{names}}. Set another language as default first.',\n 'language.active.success': 'Active languages retrieved successfully',\n 'language.set.default.success': 'Default language updated successfully',\n 'language.get.default.success': 'Default language retrieved successfully',\n\n // Translation key CRUD (API keys)\n 'translation.key.create.success': 'Translation key created successfully',\n 'translation.key.create.many.success':\n '{{count}} translation keys created successfully',\n 'translation.key.get.success': 'Translation key retrieved successfully',\n 'translation.key.get.by.ids.success':\n 'Translation keys retrieved successfully by Ids',\n 'translation.key.get.by.filter.success':\n 'Translation keys retrieved successfully by filter',\n 'translation.key.get.all.success': 'Translation keys retrieved successfully',\n 'translation.key.update.success': 'Translation key updated successfully',\n 'translation.key.update.many.success':\n '{{count}} translation keys updated successfully',\n 'translation.key.delete.success': 'Translation key deleted successfully',\n 'translation.key.restore.success': 'Translation key restored successfully',\n 'translation.key.modules.success': 'Modules retrieved successfully',\n 'translation.key.readonly.delete.forbidden':\n 'Cannot delete readonly translation keys: {{keys}}',\n 'translation.key.readonly.update.forbidden':\n 'Cannot modify key or module of system translation keys',\n 'translation.key.duplicate.key.in.module':\n 'Translation key \"{{key}}\" already exists in module \"{{module}}\"',\n\n // Translation CRUD (API keys)\n 'translation.create.success': 'Translation created successfully',\n 'translation.create.many.success':\n '{{count}} translations created successfully',\n 'translation.get.success': 'Translation retrieved successfully',\n 'translation.get.by.ids.success':\n 'Translations retrieved successfully by Ids',\n 'translation.get.by.filter.success':\n 'Translations retrieved successfully by filter',\n 'translation.get.all.success': 'Translations retrieved successfully',\n 'translation.update.success': 'Translation updated successfully',\n 'translation.update.many.success':\n '{{count}} translations updated successfully',\n 'translation.delete.success': 'Translation deleted successfully',\n 'translation.restore.success': 'Translation restored successfully',\n 'translation.by.language.success': 'Translations retrieved successfully',\n\n // pages/localization-container/localization-container.page.ts\n 'localization.title': 'Localization',\n 'localization.subtitle': 'Manage languages and translations',\n 'localization.tabs.languages': 'Languages',\n 'localization.tabs.keys': 'Keys',\n\n // pages/language-list/language-list.page.ts\n 'localization.language.title': 'Languages',\n 'localization.language.subtitle':\n 'Manage available languages for your application',\n 'localization.language.new': 'Add Language',\n 'localization.language.code': 'Language Code',\n 'localization.language.name': 'Language Name',\n 'localization.language.native.name': 'Native Name',\n 'localization.language.direction': 'Text Direction',\n 'localization.language.rtl': 'RTL',\n 'localization.language.ltr': 'LTR',\n 'localization.language.default': 'Default',\n 'localization.language.set.default': 'Set as Default',\n 'localization.language.empty':\n 'No languages configured. Add a language to get started.',\n 'localization.language.confirm.set.default':\n 'Set \"{{name}}\" as the default language?',\n 'localization.language.delete.title': 'Delete Language',\n 'localization.language.default.delete.forbidden':\n 'Cannot delete the default language. Set another language as default first.',\n 'localization.language.readonly.delete.forbidden':\n 'This is a system language and cannot be deleted',\n\n // pages/language-form/language-form.page.ts\n 'localization.language.edit': 'Edit Language',\n 'localization.language.readonly.edit.hint':\n 'This is a system language — its code, name, native name, and direction cannot be changed',\n 'localization.placeholder.code': 'en',\n 'localization.language.iso.code.hint':\n 'ISO 639-1 language code (e.g., en, ar, fr)',\n 'localization.placeholder.name': 'English',\n 'localization.placeholder.native.name': 'English',\n 'localization.language.native.name.hint':\n 'Name in the native language (e.g., العربية for Arabic)',\n 'localization.language.display.order': 'Display Order',\n 'localization.language.direction.ltr': 'Left to Right (LTR)',\n 'localization.language.direction.rtl': 'Right to Left (RTL)',\n 'localization.validation.code.required': 'Language code is required',\n 'localization.validation.code.max.length':\n 'Language code must be at most 10 characters',\n 'localization.validation.name.required': 'Language name is required',\n 'localization.validation.name.max.length':\n 'Language name must be at most 100 characters',\n\n // pages/translation-key-list/translation-key-list.page.ts\n 'localization.key.title': 'Translation Keys',\n 'localization.key.subtitle': 'Manage translation keys for your application',\n 'localization.key.new': 'Add Key',\n 'localization.key.filter.module': 'Filter by module',\n 'localization.key.module': 'Module',\n 'localization.key.name': 'Key Name',\n 'localization.key.default.message': 'Default Message',\n 'localization.key.translations': 'Translations',\n 'localization.key.empty': 'No translation keys found',\n 'localization.key.delete.title': 'Delete Translation Key',\n 'localization.key.readonly.delete.forbidden':\n 'This is a system translation key and cannot be deleted',\n 'localization.key.readonly.edit.hint':\n 'This is a system key — its key name and module cannot be changed',\n\n // pages/translation-key-form/translation-key-form.page.ts\n 'localization.key.edit': 'Edit Key',\n 'localization.key.about': 'Key Information',\n 'localization.placeholder.key.name': 'button.submit',\n 'localization.key.select.module': 'Select or enter module',\n 'localization.placeholder.default.message': 'Enter default value (English)',\n 'localization.key.description': 'Description',\n 'localization.placeholder.key.description':\n 'Optional description for translators',\n 'localization.key.variables': 'Variables',\n 'localization.key.variables.placeholder': 'e.g., name, count, date',\n 'localization.key.variables.hint':\n 'Enter variable names used in this translation',\n 'localization.key.translations.section': 'Translations',\n 'localization.key.no.languages': 'No active languages configured',\n 'localization.key.enter.translation': 'Enter translation',\n 'localization.validation.key.required': 'Translation key is required',\n 'localization.validation.default.message.required':\n 'Default message is required',\n};\n","import { Service } from '@angular/core';\nimport { ApiResourceService, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateLanguageDto,\n ILanguage,\n IUpdateLanguageDto,\n} from '../interfaces/language.interface';\n\n@Service()\nexport class LanguageApiService extends ApiResourceService<\n ICreateLanguageDto | IUpdateLanguageDto,\n ILanguage\n> {\n constructor() {\n super('language', 'localization');\n }\n\n setDefault(id: string): Observable<ISingleResponse<ILanguage>> {\n return this.http.post<ISingleResponse<ILanguage>>(\n `${this.baseUrl}/set-default`,\n { id },\n );\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { inject, Service } from '@angular/core';\nimport { APP_CONFIG } from '@flusys/ng-core';\nimport { IListResponse, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { ILanguage, ITranslationsMap } from '../interfaces/language.interface';\n\n@Service()\nexport class LocalizationApiService {\n private readonly http = inject(HttpClient);\n private readonly appConfig = inject(APP_CONFIG);\n\n private get baseUrl(): string {\n return `${this.appConfig.apiBaseUrl}/localization`;\n }\n\n getActiveLanguages(): Observable<IListResponse<ILanguage>> {\n return this.http.post<IListResponse<ILanguage>>(`${this.baseUrl}/language/get-active`, {});\n }\n\n getTranslationsByLanguage(languageCode: string, modules?: string[]): Observable<ISingleResponse<ITranslationsMap>> {\n return this.http.post<ISingleResponse<ITranslationsMap>>(\n `${this.baseUrl}/translation/get-by-language`,\n { languageCode, ...(modules?.length ? { modules } : {}) },\n );\n }\n}\n","import { inject, Service } from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport { firstValueFrom } from 'rxjs';\nimport { LocalizationApiService } from './localization-api.service';\nimport { LocalizationStateService } from './localization-state.service';\n\n@Service()\nexport class LocalizationInitializerService {\n apiService: LocalizationApiService = inject(LOCALIZATION_API_SERVICE, {\n optional: false,\n }) as LocalizationApiService;\n\n stateService: LocalizationStateService = inject(LOCALIZATION_STATE_SERVICE, {\n optional: false,\n }) as unknown as LocalizationStateService;\n\n async initialize(\n initialFallbackMessages?: Record<string, string>,\n ): Promise<void> {\n try {\n this.stateService.setLoading(true);\n if (initialFallbackMessages) {\n this.stateService.updateFallbackMessages(initialFallbackMessages);\n }\n const languagesResponse = await firstValueFrom(\n this.apiService.getActiveLanguages(),\n );\n if (languagesResponse.success && languagesResponse.data) {\n this.stateService.setAvailableLanguages(languagesResponse.data);\n\n const savedCode = this.stateService.getSavedLanguageCode();\n let selectedLanguage = languagesResponse.data.find(\n (l) => l.code === savedCode,\n );\n\n if (!selectedLanguage) {\n selectedLanguage = languagesResponse.data.find((l) => l.isDefault);\n }\n\n if (!selectedLanguage && languagesResponse.data.length > 0) {\n selectedLanguage = languagesResponse.data[0];\n }\n\n if (selectedLanguage) {\n this.stateService.setCurrentLanguage(selectedLanguage);\n }\n }\n } catch {\n return;\n } finally {\n this.stateService.setLoading(false);\n }\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport { ApplicationRef, computed, effect, inject, signal, Service } from '@angular/core';\nimport { PlatformService } from '@flusys/ng-shared';\nimport { STORAGE_KEYS } from '../constants/localization.constants';\nimport { ILanguage, ITranslationsMap } from '../interfaces/language.interface';\n\n@Service()\nexport class LocalizationStateService {\n private readonly platformService = inject(PlatformService);\n private readonly document = inject(DOCUMENT);\n private readonly appRef = inject(ApplicationRef);\n private readonly _loadedModules = new Set<string>();\n private readonly _currentLanguage = signal<ILanguage | null>(null);\n private readonly _availableLanguages = signal<ILanguage[]>([]);\n private readonly _translations = signal<ITranslationsMap>({});\n private readonly _fallbackMessages = signal<ITranslationsMap>({});\n private readonly _isLoading = signal<boolean>(false);\n\n readonly availableLanguages = this._availableLanguages.asReadonly();\n readonly translations = this._translations.asReadonly();\n readonly fallbackMessages = this._fallbackMessages.asReadonly();\n readonly isLoading = this._isLoading.asReadonly();\n\n readonly currentLanguageCode = computed(\n () => this._currentLanguage()?.code ?? 'en',\n );\n\n constructor() {\n effect(() => {\n const language = this._currentLanguage();\n if (language && !this.platformService.isServer) {\n this.document.documentElement.dir = language.direction ?? 'ltr';\n this.document.documentElement.lang = language.code;\n try {\n localStorage.setItem(STORAGE_KEYS.CURRENT_LANGUAGE, language.code);\n } catch {\n return;\n }\n }\n });\n\n effect(() => {\n this._translations();\n setTimeout(() => this.appRef.tick(), 0);\n });\n }\n\n setCurrentLanguage(language: ILanguage): void {\n this._currentLanguage.set(language);\n }\n\n setAvailableLanguages(languages: ILanguage[]): void {\n this._availableLanguages.set(languages);\n }\n\n setTranslations(translations: ITranslationsMap): void {\n this._translations.set(translations);\n }\n\n mergeTranslations(translations: ITranslationsMap): void {\n this._translations.update((current) => ({ ...current, ...translations }));\n }\n\n setLoading(loading: boolean): void {\n this._isLoading.set(loading);\n }\n\n getSavedLanguageCode(): string | null {\n if (this.platformService.isServer) return null;\n try {\n return localStorage.getItem(STORAGE_KEYS.CURRENT_LANGUAGE);\n } catch {\n return null;\n }\n }\n\n isModuleLoaded(module: string): boolean {\n return this._loadedModules.has(module);\n }\n\n markModuleLoaded(module: string): void {\n this._loadedModules.add(module);\n }\n\n getLoadedModules(): string[] {\n return Array.from(this._loadedModules);\n }\n\n clearLoadedModules(): void {\n this._loadedModules.clear();\n }\n\n updateFallbackMessages(messages: ITranslationsMap): void {\n this._fallbackMessages.update((current) => ({ ...current, ...messages }));\n }\n}\n","import { Service } from '@angular/core';\nimport {\n ApiResourceService,\n IListResponse,\n ISingleResponse,\n} from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport { ITranslation } from '../interfaces/translation.interface';\n\nexport interface ICreateTranslationDto {\n languageId: string;\n translationKeyId: string;\n value: string;\n isVerified?: boolean;\n isActive?: boolean;\n}\n\nexport interface IUpdateTranslationDto extends Partial<ICreateTranslationDto> {\n id: string;\n}\n\nexport interface IBulkUpdateTranslationDto {\n id?: string;\n languageId: string;\n translationKeyId: string;\n value: string;\n isVerified?: boolean;\n}\n\n@Service()\nexport class TranslationApiService extends ApiResourceService<\n ICreateTranslationDto | IUpdateTranslationDto,\n ITranslation\n> {\n constructor() {\n super('translation', 'localization');\n }\n\n getByKeyId(\n translationKeyId: string,\n ): Observable<IListResponse<ITranslation>> {\n return this.http.post<IListResponse<ITranslation>>(\n `${this.baseUrl}/get-all`,\n {\n pagination: { currentPage: 0, pageSize: 1000 },\n filter: { translationKeyId },\n sort: {},\n },\n );\n }\n\n getCounts(): Observable<ISingleResponse<Record<string, number>>> {\n return this.http.post<ISingleResponse<Record<string, number>>>(\n `${this.baseUrl}/get-counts`,\n {},\n );\n }\n\n bulkUpdate(\n translations: IBulkUpdateTranslationDto[],\n ): Observable<IListResponse<ITranslation>> {\n return this.http.post<IListResponse<ITranslation>>(\n `${this.baseUrl}/update-many-values`,\n { translations },\n );\n }\n}\n","import { Service } from '@angular/core';\nimport { ApiResourceService, ISingleResponse } from '@flusys/ng-shared';\nimport { Observable } from 'rxjs';\nimport {\n ICreateTranslationKeyDto,\n ITranslationKey,\n IUpdateTranslationKeyDto,\n} from '../interfaces/translation-key.interface';\n\n@Service()\nexport class TranslationKeyApiService extends ApiResourceService<\n ICreateTranslationKeyDto | IUpdateTranslationKeyDto,\n ITranslationKey\n> {\n constructor() {\n super('translation-key', 'localization');\n }\n\n getModules(): Observable<ISingleResponse<string[]>> {\n return this.http.post<ISingleResponse<string[]>>(\n `${this.baseUrl}/get-modules`,\n {},\n );\n }\n}\n","import { inject, Service } from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport { firstValueFrom, from, Observable } from 'rxjs';\nimport { LOCALIZATION_CONFIG } from '../interfaces/localization-config.interface';\nimport { LocalizationApiService } from './localization-api.service';\nimport { LocalizationStateService } from './localization-state.service';\n\n@Service()\nexport class TranslationLoaderService {\n private readonly DEFAULT_INITIAL_MODULES = ['shared', 'layout'];\n private readonly config = inject(LOCALIZATION_CONFIG, { optional: true });\n apiService: LocalizationApiService = inject(LOCALIZATION_API_SERVICE, {\n optional: false,\n }) as LocalizationApiService;\n\n stateService: LocalizationStateService = inject(LOCALIZATION_STATE_SERVICE, {\n optional: false,\n }) as unknown as LocalizationStateService;\n\n private loadToken = 0;\n private pendingReloadModules: string[] = [];\n\n async loadTranslations(\n languageCode: string,\n clearModules = false,\n ): Promise<void> {\n const token = ++this.loadToken;\n const isCurrent = () => token === this.loadToken;\n const strategy = this.config?.loadStrategy ?? 'all';\n\n let previouslyLoadedModules: string[] = [];\n if (clearModules) {\n previouslyLoadedModules = Array.from(\n new Set([\n ...this.pendingReloadModules,\n ...this.stateService.getLoadedModules(),\n ]),\n );\n this.pendingReloadModules = previouslyLoadedModules;\n this.stateService.clearLoadedModules();\n }\n\n this.stateService.setLoading(true);\n\n try {\n if (strategy === 'all') {\n await this.loadAndSetTranslations(languageCode, undefined, isCurrent);\n } else {\n const modules =\n this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;\n await this.loadAndSetTranslations(languageCode, modules, isCurrent);\n if (isCurrent() && previouslyLoadedModules.length > 0) {\n await this.reloadModules(\n languageCode,\n previouslyLoadedModules,\n isCurrent,\n );\n }\n }\n } catch {\n return;\n } finally {\n if (isCurrent()) {\n this.pendingReloadModules = [];\n this.stateService.setLoading(false);\n }\n }\n }\n\n private async loadAndSetTranslations(\n languageCode: string,\n modules: string[] | undefined,\n isCurrent: () => boolean,\n ): Promise<void> {\n const response = await firstValueFrom(\n this.apiService.getTranslationsByLanguage(languageCode, modules),\n );\n if (isCurrent() && response?.success && response.data) {\n this.stateService.setTranslations(response.data);\n if (modules) {\n modules.forEach((m) => this.stateService.markModuleLoaded(m));\n }\n }\n }\n\n private async reloadModules(\n languageCode: string,\n modules: string[],\n isCurrent: () => boolean,\n ): Promise<void> {\n const initialModules =\n this.config?.initialModules ?? this.DEFAULT_INITIAL_MODULES;\n const additionalModules = modules.filter(\n (m) => !initialModules.includes(m),\n );\n\n if (additionalModules.length === 0) return;\n\n const response = await firstValueFrom(\n this.apiService.getTranslationsByLanguage(\n languageCode,\n additionalModules,\n ),\n );\n\n if (isCurrent() && response?.success && response.data) {\n this.stateService.mergeTranslations(response.data);\n additionalModules.forEach((m) => this.stateService.markModuleLoaded(m));\n }\n }\n\n loadTranslationsAsync(\n languageCode: string,\n clearModules = false,\n ): Observable<void> {\n return from(this.loadTranslations(languageCode, clearModules));\n }\n}\n","import { Component, DestroyRef, computed, inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MenuComponent, MenuItem, UiIconComponent } from '@flusys/ng-ui';\nimport { LocalizationStateService } from '../../services/localization-state.service';\nimport { TranslationLoaderService } from '../../services/translation-loader.service';\n\n@Component({\n selector: 'lib-language-selector',\n imports: [MenuComponent, UiIconComponent],\n host: { class: 'relative' },\n template: `\n <button\n type=\"button\"\n class=\"layout-topbar-action\"\n [class.layout-topbar-action-highlight]=\"menu.visible()\"\n (click)=\"menu.toggle($event)\"\n >\n <ui-icon name=\"globe\"></ui-icon>\n <span class=\"font-semibold\">{{\n selectedLanguage()?.nativeName ||\n selectedLanguage()?.name ||\n selectedLanguageCode()\n }}</span>\n </button>\n <f-menu\n #menu\n [model]=\"menuItems()\"\n [popup]=\"true\"\n class=\"absolute left-[0]\"\n [style]=\"{ 'inset-inline-end': '0' }\"\n />\n `,\n})\nexport class LanguageSelectorComponent {\n private readonly localizationState = inject(LocalizationStateService);\n private readonly translationLoader = inject(TranslationLoaderService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly languages = this.localizationState.availableLanguages;\n\n readonly selectedLanguageCode = this.localizationState.currentLanguageCode;\n readonly selectedLanguage = computed(\n () =>\n this.languages().find((l) => l.code === this.selectedLanguageCode()) ??\n null,\n );\n\n readonly menuItems = computed<MenuItem[]>(() =>\n this.languages().map((lang) => ({\n label: lang.nativeName || lang.name,\n badge: lang.code.toUpperCase(),\n selected: lang.code === this.selectedLanguageCode(),\n command: () => this.onLanguageSelect(lang.code),\n })),\n );\n\n onLanguageSelect(code: string): void {\n const language = this.languages().find((l) => l.code === code);\n if (language) {\n this.localizationState.setCurrentLanguage(language);\n this.translationLoader\n .loadTranslationsAsync(code, true)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe();\n }\n }\n}\n","import {\n Component,\n DestroyRef,\n computed,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MenuComponent, MenuItem } from '@flusys/ng-ui';\nimport { LocalizationStateService } from '../../services/localization-state.service';\nimport { TranslationLoaderService } from '../../services/translation-loader.service';\n\n@Component({\n selector: 'lib-language-selector-panel',\n imports: [MenuComponent],\n host: {\n class: 'hidden absolute z-50 top-[24px] p-3 min-w-[180px]',\n style: 'inset-inline-end: 0;',\n },\n template: `<f-menu [model]=\"menuItems()\" />`,\n})\nexport class LanguageSelectorPanelComponent {\n private readonly localizationState = inject(LocalizationStateService);\n private readonly translationLoader = inject(TranslationLoaderService);\n private readonly destroyRef = inject(DestroyRef);\n\n readonly languages = this.localizationState.availableLanguages;\n\n private readonly _selectedLanguageCode = signal<string>(\n this.localizationState.currentLanguageCode(),\n );\n readonly selectedLanguageCode = this._selectedLanguageCode.asReadonly();\n\n readonly menuItems = computed<MenuItem[]>(() =>\n this.languages().map((lang) => ({\n label: lang.nativeName || lang.name,\n badge: lang.code.toUpperCase(),\n selected: lang.code === this.selectedLanguageCode(),\n command: () => this.onLanguageSelect(lang.code),\n })),\n );\n\n constructor() {\n effect(() => {\n const currentCode = this.localizationState.currentLanguageCode();\n if (currentCode !== this._selectedLanguageCode()) {\n this._selectedLanguageCode.set(currentCode);\n }\n });\n }\n\n onLanguageSelect(code: string): void {\n const language = this.languages().find((l) => l.code === code);\n if (language) {\n this._selectedLanguageCode.set(code);\n this.localizationState.setCurrentLanguage(language);\n this.translationLoader\n .loadTranslationsAsync(code, true)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe();\n }\n }\n}\n","import {\n EnvironmentProviders,\n inject,\n provideAppInitializer,\n Provider,\n} from '@angular/core';\nimport {\n LOCALIZATION_API_SERVICE,\n LOCALIZATION_STATE_SERVICE,\n} from '@flusys/ng-core';\nimport {\n LAYOUT_LANGUAGE_SELECTOR,\n LAYOUT_LANGUAGE_SELECTOR_PANEL,\n} from '@flusys/ng-layout';\nimport { LanguageSelectorPanelComponent } from '../components/language-selector-panel/language-selector-panel.component';\nimport { LanguageSelectorComponent } from '../components/language-selector/language-selector.component';\nimport {\n ILocalizationConfig,\n LOCALIZATION_CONFIG,\n} from '../interfaces/localization-config.interface';\nimport { LocalizationApiService } from '../services/localization-api.service';\nimport { LocalizationInitializerService } from '../services/localization-initializer.service';\nimport { LocalizationStateService } from '../services/localization-state.service';\n\nexport function provideLocalization(\n config: ILocalizationConfig,\n initialFallbackMessages?: Record<string, string>,\n): Array<Provider | EnvironmentProviders> {\n const providers: Array<Provider | EnvironmentProviders> = [\n // 1. Value/Existing Providers\n { provide: LOCALIZATION_CONFIG, useValue: config },\n {\n provide: LOCALIZATION_STATE_SERVICE,\n useExisting: LocalizationStateService,\n },\n { provide: LOCALIZATION_API_SERVICE, useExisting: LocalizationApiService },\n\n // 2. The Service itself\n LocalizationInitializerService,\n\n // 3. The modern Initializer\n provideAppInitializer(() => {\n const initializer = inject(LocalizationInitializerService);\n return initializer.initialize(initialFallbackMessages);\n }),\n ];\n\n if (config.enableLayoutSelector) {\n providers.push(\n {\n provide: LAYOUT_LANGUAGE_SELECTOR,\n useValue: LanguageSelectorComponent,\n },\n {\n provide: LAYOUT_LANGUAGE_SELECTOR_PANEL,\n useValue: LanguageSelectorPanelComponent,\n },\n );\n }\n\n return providers;\n}\n","import { inject } from '@angular/core';\nimport { Routes } from '@angular/router';\nimport {\n LANGUAGE_PERMISSIONS,\n PermissionValidatorService,\n permissionGuard,\n SHARED_MESSAGES,\n resolveTranslationModule,\n TRANSLATION_KEY_PERMISSIONS,\n} from '@flusys/ng-shared';\nimport { LOCALIZATION_MESSAGES } from '../constants/messages';\n\n/**\n * Resolves which localization tab the current user should land on when\n * navigating to the bare `/localization` route. Mirrors the tab\n * visibility order in LocalizationContainerPage.visibleTabs so the\n * redirect never points at a tab the user can't actually see.\n */\nfunction resolveLocalizationDefaultTab(): string {\n const permissionValidator = inject(PermissionValidatorService);\n\n if (permissionValidator.hasPermission(LANGUAGE_PERMISSIONS.READ)) {\n return 'languages';\n }\n\n if (permissionValidator.hasPermission(TRANSLATION_KEY_PERMISSIONS.READ)) {\n return 'keys';\n }\n\n return 'languages';\n}\n\nexport const LOCALIZATION_ROUTES: Routes = [\n {\n path: '',\n resolve: { translations: resolveTranslationModule({ modules: ['localization'], fallbackMessages: { ...LOCALIZATION_MESSAGES, ...SHARED_MESSAGES } }) },\n loadComponent: () =>\n import('../pages/localization-container/localization-container.page').then(\n (m) => m.LocalizationContainerPage,\n ),\n children: [\n // Languages Management\n {\n path: 'languages',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/language-list/language-list.page').then((m) => m.LanguageListPage),\n },\n {\n path: 'new',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.CREATE)],\n loadComponent: () =>\n import('../pages/language-form/language-form.page').then((m) => m.LanguageFormPage),\n },\n {\n path: ':id',\n canActivate: [permissionGuard(LANGUAGE_PERMISSIONS.UPDATE)],\n loadComponent: () =>\n import('../pages/language-form/language-form.page').then((m) => m.LanguageFormPage),\n },\n ],\n },\n\n // Translation Keys Management\n {\n path: 'keys',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.READ)],\n children: [\n {\n path: '',\n loadComponent: () =>\n import('../pages/translation-key-list/translation-key-list.page').then(\n (m) => m.TranslationKeyListPage,\n ),\n },\n {\n path: 'new',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.CREATE)],\n loadComponent: () =>\n import('../pages/translation-key-form/translation-key-form.page').then(\n (m) => m.TranslationKeyFormPage,\n ),\n },\n {\n path: ':id',\n canActivate: [permissionGuard(TRANSLATION_KEY_PERMISSIONS.UPDATE)],\n loadComponent: () =>\n import('../pages/translation-key-form/translation-key-form.page').then(\n (m) => m.TranslationKeyFormPage,\n ),\n },\n ],\n },\n\n // Default redirect to the first tab the user has permission to see\n {\n path: '',\n redirectTo: () => resolveLocalizationDefaultTab(),\n pathMatch: 'full',\n },\n ],\n },\n];\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/ng-localization",
3
- "version": "9.1.1",
3
+ "version": "9.2.0",
4
4
  "description": "Localization module for multi-language support in FLUSYS Angular apps",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -8,10 +8,10 @@
8
8
  "@angular/core": ">=22.0.0",
9
9
  "@angular/forms": ">=22.0.0",
10
10
  "@angular/router": ">=22.0.0",
11
- "@flusys/ng-core": ">=9.1.1",
12
- "@flusys/ng-layout": ">=9.1.1",
13
- "@flusys/ng-shared": ">=9.1.1",
14
- "@flusys/ng-ui": ">=9.1.1",
11
+ "@flusys/ng-core": ">=9.2.0",
12
+ "@flusys/ng-layout": ">=9.2.0",
13
+ "@flusys/ng-shared": ">=9.2.0",
14
+ "@flusys/ng-ui": ">=9.2.0",
15
15
  "rxjs": "^7.8.0"
16
16
  },
17
17
  "sideEffects": false,
@@ -180,6 +180,8 @@ export declare class TranslationLoaderService {
180
180
  private readonly config;
181
181
  apiService: LocalizationApiService;
182
182
  stateService: LocalizationStateService;
183
+ private loadToken;
184
+ private pendingReloadModules;
183
185
  loadTranslations(languageCode: string, clearModules?: boolean): Promise<void>;
184
186
  private loadAndSetTranslations;
185
187
  private reloadModules;
@@ -1 +0,0 @@
1
- {"version":3,"file":"flusys-ng-localization-language-form.page-BdxZ6meb.mjs","names":[],"sources":["../../../projects/ng-localization/pages/language-form/language-form.page.ts"],"sourcesContent":["import {\n Component,\n computed,\n DestroyRef,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { FormsModule } from '@angular/forms';\nimport {\n disabled,\n form,\n FormField,\n maxLength,\n required,\n} from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport {\n CardComponent,\n CheckboxComponent,\n FButtonDirective,\n InputTextDirective,\n MessageService,\n SelectComponent,\n UiIconComponent,\n} from '@flusys/ng-ui';\nimport {\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { finalize, from } from 'rxjs';\nimport {\n ICreateLanguageDto,\n ILanguage,\n IUpdateLanguageDto,\n} from '../../interfaces/language.interface';\nimport { LanguageApiService } from '../../services/language-api.service';\n\ninterface ILanguageFormModel {\n code: string;\n name: string;\n nativeName: string;\n direction: 'ltr' | 'rtl';\n serial: string;\n isActive: boolean;\n isDefault: boolean;\n}\n\n@Component({\n selector: 'lib-language-form-page',\n imports: [\n CardComponent,\n InputTextDirective,\n SelectComponent,\n CheckboxComponent,\n FButtonDirective,\n UiIconComponent,\n FormsModule,\n FormField,\n TranslatePipe,\n ],\n providers: [MessageService],\n template: `\n <f-card>\n <ng-template #header>\n <div class=\"flex justify-between items-center p-4\">\n <h2 class=\"text-xl font-semibold m-0\">\n {{\n isEditMode()\n ? ('localization.language.edit' | translate)\n : ('localization.language.new' | translate)\n }}\n </h2>\n </div>\n </ng-template>\n\n <form\n (ngSubmit)=\"onSubmit()\"\n class=\"grid grid-cols-1 md:grid-cols-2 gap-4\"\n >\n <!-- Language Code -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"code\" class=\"font-medium\"\n >{{ 'localization.language.code' | translate }} *</label\n >\n <input\n fInputText\n id=\"code\"\n [formField]=\"formTree.code\"\n [placeholder]=\"'localization.placeholder.code' | translate\"\n />\n <small class=\"text-muted-color\">{{\n 'localization.language.iso.code.hint' | translate\n }}</small>\n </div>\n\n <!-- Language Name -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"name\" class=\"font-medium\"\n >{{ 'localization.language.name' | translate }} *</label\n >\n <input\n fInputText\n id=\"name\"\n [formField]=\"formTree.name\"\n [placeholder]=\"'localization.placeholder.name' | translate\"\n />\n </div>\n\n <!-- Native Name -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"nativeName\" class=\"font-medium\">{{\n 'localization.language.native.name' | translate\n }}</label>\n <input\n fInputText\n id=\"nativeName\"\n [formField]=\"formTree.nativeName\"\n [placeholder]=\"'localization.placeholder.native.name' | translate\"\n />\n <small class=\"text-muted-color\">{{\n 'localization.language.native.name.hint' | translate\n }}</small>\n </div>\n\n <!-- Text Direction -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"direction\" class=\"font-medium\"\n >{{ 'localization.language.direction' | translate }} *</label\n >\n <f-select\n id=\"direction\"\n [ngModel]=\"formModel().direction\"\n (ngModelChange)=\"updateDirection($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"directionOptions()\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [disabled]=\"isReadonly()\"\n class=\"w-full\"\n />\n @if (isReadonly()) {\n <small class=\"text-muted-color\">{{\n 'localization.language.readonly.edit.hint' | translate\n }}</small>\n }\n </div>\n\n <!-- Display Order -->\n <div class=\"flex flex-col gap-2\">\n <label for=\"serial\" class=\"font-medium\">{{\n 'localization.language.display.order' | translate\n }}</label>\n <input\n fInputText\n id=\"serial\"\n type=\"number\"\n [formField]=\"formTree.serial\"\n [placeholder]=\"'shared.display.order.placeholder' | translate\"\n />\n </div>\n\n <!-- Empty cell for alignment -->\n <div class=\"hidden md:block\"></div>\n\n <!-- Checkboxes -->\n <div class=\"flex items-center gap-6 md:col-span-2 pt-4\">\n <f-checkbox [formField]=\"formTree.isActive\" [label]=\"'shared.active' | translate\" />\n <f-checkbox [formField]=\"formTree.isDefault\" [label]=\"'localization.language.default' | translate\" />\n </div>\n\n <!-- Actions -->\n <div class=\"flex justify-end gap-4 md:col-span-2 pt-4\">\n <button\n fButton\n type=\"button\"\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onCancel()\"\n >\n <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>\n </button>\n <button\n fButton\n type=\"submit\"\n [disabled]=\"!isFormValid() || isSaving()\"\n >\n @if (isSaving()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n }\n <span pButtonLabel>{{ \n isEditMode()\n ? ('shared.update' | translate)\n : ('shared.create' | translate)\n }}</span>\n </button>\n </div>\n </form>\n </f-card>\n `,\n})\nexport class LanguageFormPage {\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly languageService = inject(LanguageApiService);\n private readonly messageService = inject(MessageService);\n private readonly translateAdapter = inject(TranslateService, {\n optional: true,\n });\n private readonly destroyRef = inject(DestroyRef);\n\n private readonly routeParams = toSignal(this.route.paramMap);\n private loadTriggered = false;\n\n readonly isSaving = signal(false);\n readonly existingLanguage = signal<ILanguage | null>(null);\n readonly isEditMode = computed(() => !!this.existingLanguage());\n readonly isReadonly = computed(() => this.existingLanguage()?.isReadonly ?? false);\n\n private translate(\n key: string,\n vars?: Record<string, string | number>,\n ): string {\n return this.translateAdapter?.translate(key, vars) ?? key;\n }\n\n readonly directionOptions = computed(() => [\n {\n label: this.translate('localization.language.direction.ltr'),\n value: 'ltr',\n },\n {\n label: this.translate('localization.language.direction.rtl'),\n value: 'rtl',\n },\n ]);\n\n readonly formModel = signal<ILanguageFormModel>({\n code: '',\n name: '',\n nativeName: '',\n direction: 'ltr',\n serial: '',\n isActive: true,\n isDefault: false,\n });\n\n readonly formTree = form(this.formModel, (f) => {\n required(f.code, {\n message: this.translate('localization.validation.code.required'),\n });\n maxLength(f.code, 10, {\n message: this.translate('localization.validation.code.max.length'),\n });\n required(f.name, {\n message: this.translate('localization.validation.name.required'),\n });\n maxLength(f.name, 100, {\n message: this.translate('localization.validation.name.max.length'),\n });\n disabled(f.code, { when: () => this.isReadonly() });\n disabled(f.name, { when: () => this.isReadonly() });\n disabled(f.nativeName, { when: () => this.isReadonly() });\n });\n\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.code.trim().length > 0 && model.name.trim().length > 0;\n });\n\n constructor() {\n effect(() => {\n const params = this.routeParams();\n if (!params || this.loadTriggered) return;\n\n this.loadTriggered = true;\n const id = params.get('id');\n if (id && id !== 'new') {\n this.loadLanguage(id);\n }\n });\n }\n\n updateDirection(value: 'ltr' | 'rtl'): void {\n this.formModel.update((m) => ({ ...m, direction: value }));\n }\n\n loadLanguage(id: string): void {\n this.isSaving.set(true);\n from(this.languageService.findById(id))\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isSaving.set(false)),\n )\n .subscribe({\n next: (response) => {\n if (response.success && response.data) {\n this.existingLanguage.set(response.data);\n this.formModel.set(this.toFormModel(response.data));\n }\n },\n error: () => this.router.navigate(['/localization/languages']),\n });\n }\n\n private toFormModel(language: ILanguage): ILanguageFormModel {\n return {\n code: language.code,\n name: language.name,\n nativeName: language.nativeName ?? '',\n direction: language.direction ?? 'ltr',\n serial: language.serial?.toString() ?? '',\n isActive: language.isActive,\n isDefault: language.isDefault,\n };\n }\n\n onSubmit(): void {\n if (!this.isFormValid()) return;\n\n this.isSaving.set(true);\n const model = this.formModel();\n\n const dto = {\n code: model.code,\n name: model.name,\n nativeName: model.nativeName || undefined,\n direction: model.direction,\n serial: model.serial ? parseInt(model.serial, 10) : undefined,\n isActive: model.isActive,\n isDefault: model.isDefault,\n };\n\n const operation$ = this.isEditMode()\n ? from(\n this.languageService.update({\n id: this.existingLanguage()!.id,\n ...dto,\n } as IUpdateLanguageDto),\n )\n : from(this.languageService.insert(dto as ICreateLanguageDto));\n\n operation$\n .pipe(\n takeUntilDestroyed(this.destroyRef),\n finalize(() => this.isSaving.set(false)),\n )\n .subscribe({\n next: (response) => {\n if (response.success) {\n this.messageService.add({\n severity: 'success',\n summary: this.translate('shared.success'),\n detail: response.messageKey\n ? this.translate(\n response.messageKey,\n response.messageVariables as Record<\n string,\n string | number\n >,\n )\n : (response.message ?? ''),\n });\n this.router.navigate(['/localization/languages']);\n }\n },\n });\n }\n\n onCancel(): void {\n this.router.navigate(['/localization/languages']);\n }\n}\n"],"mappings":";;;;;;;;;;;AA0MA,IAAa,mBAAb,MAAa,iBAAgB;CACV,SAAS,OAAO,MAAM;CACtB,QAAQ,OAAO,cAAc;CAC7B,kBAAkB,OAAO,kBAAkB;CAC3C,iBAAiB,OAAO,cAAc;CACtC,mBAAmB,OAAO,kBAAkB,EAC3D,UAAU,KACX,CAAA;CACgB,aAAa,OAAO,UAAU;CAE9B,cAAc,SAAS,KAAK,MAAM,QAAQ;CACnD,gBAAgB;CAEf,WAAW,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,mBAAmB,OAAyB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CACjD,aAAa,eAAe,CAAC,CAAC,KAAK,iBAAgB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACtD,aAAa,eAAe,KAAK,iBAAgB,CAAE,EAAE,cAAc,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAE1E,UACN,KACA,MAAsC;EAEtC,OAAO,KAAK,kBAAkB,UAAU,KAAK,IAAI,KAAK;CACxD;CAES,mBAAmB,eAAe,CACzC;EACE,OAAO,KAAK,UAAU,qCAAqC;EAC3D,OAAO;CACR,GACD;EACE,OAAO,KAAK,UAAU,qCAAqC;EAC3D,OAAO;CACR,CACF,GAAC,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,YAAY,OAA2B;EAC9C,MAAM;EACN,MAAM;EACN,YAAY;EACZ,WAAW;EACX,QAAQ;EACR,UAAU;EACV,WAAW;CACZ,GAAC,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEO,WAAW,KAAK,KAAK,YAAY,MAAK;EAC7C,SAAS,EAAE,MAAM,EACf,SAAS,KAAK,UAAU,uCAAuC,EAChE,CAAA;EACD,UAAU,EAAE,MAAM,IAAI,EACpB,SAAS,KAAK,UAAU,yCAAyC,EAClE,CAAA;EACD,SAAS,EAAE,MAAM,EACf,SAAS,KAAK,UAAU,uCAAuC,EAChE,CAAA;EACD,UAAU,EAAE,MAAM,KAAK,EACrB,SAAS,KAAK,UAAU,yCAAyC,EAClE,CAAA;EACD,SAAS,EAAE,MAAM,EAAE,YAAY,KAAK,WAAU,EAAE,CAAE;EAClD,SAAS,EAAE,MAAM,EAAE,YAAY,KAAK,WAAU,EAAE,CAAE;EAClD,SAAS,EAAE,YAAY,EAAE,YAAY,KAAK,WAAU,EAAE,CAAE;CAC1D,CAAC;CAEQ,cAAc,eAAc;EACnC,MAAM,QAAQ,KAAK,UAAS;EAC5B,OAAO,MAAM,KAAK,KAAI,CAAE,CAAC,SAAS,KAAK,MAAM,KAAK,KAAI,CAAE,CAAC,SAAS;CACpE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEF,cAAA;EACE,aAAY;GACV,MAAM,SAAS,KAAK,YAAW;GAC/B,IAAI,CAAC,UAAU,KAAK,eAAe;GAEnC,KAAK,gBAAgB;GACrB,MAAM,KAAK,OAAO,IAAI,IAAI;GAC1B,IAAI,MAAM,OAAO,OACf,KAAK,aAAa,EAAE;EAExB,CAAC;CACH;CAEA,gBAAgB,OAAoB;EAClC,KAAK,UAAU,QAAQ,OAAO;GAAE,GAAG;GAAG,WAAW;EAAK,EAAG;CAC3D;CAEA,aAAa,IAAU;EACrB,KAAK,SAAS,IAAI,IAAI;EACtB,KAAK,KAAK,gBAAgB,SAAS,EAAE,CAAC,CAAC,CACpC,KACC,mBAAmB,KAAK,UAAU,GAClC,eAAe,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CACzC,CACA,UAAU;GACT,OAAO,aAAY;IACjB,IAAI,SAAS,WAAW,SAAS,MAAM;KACrC,KAAK,iBAAiB,IAAI,SAAS,IAAI;KACvC,KAAK,UAAU,IAAI,KAAK,YAAY,SAAS,IAAI,CAAC;IACpD;GACF;GACA,aAAa,KAAK,OAAO,SAAS,CAAC,yBAAyB,CAAC;EAC9D,CAAA;CACL;CAEQ,YAAY,UAAmB;EACrC,OAAO;GACL,MAAM,SAAS;GACf,MAAM,SAAS;GACf,YAAY,SAAS,cAAc;GACnC,WAAW,SAAS,aAAa;GACjC,QAAQ,SAAS,QAAQ,SAAQ,KAAM;GACvC,UAAU,SAAS;GACnB,WAAW,SAAS;EACrB;CACH;CAEA,WAAQ;EACN,IAAI,CAAC,KAAK,YAAW,GAAI;EAEzB,KAAK,SAAS,IAAI,IAAI;EACtB,MAAM,QAAQ,KAAK,UAAS;EAE5B,MAAM,MAAM;GACV,MAAM,MAAM;GACZ,MAAM,MAAM;GACZ,YAAY,MAAM,cAAc;GAChC,WAAW,MAAM;GACjB,QAAQ,MAAM,SAAS,SAAS,MAAM,QAAQ,EAAE,IAAI;GACpD,UAAU,MAAM;GAChB,WAAW,MAAM;EAClB;EAWD,CATmB,KAAK,WAAU,IAC9B,KACE,KAAK,gBAAgB,OAAO;GAC1B,IAAI,KAAK,iBAAgB,CAAG,CAAC;GAC7B,GAAG;EACkB,CAAA,CAAC,IAE1B,KAAK,KAAK,gBAAgB,OAAO,GAAyB,CAAC,EAE/D,CACG,KACC,mBAAmB,KAAK,UAAU,GAClC,eAAe,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CACzC,CACA,UAAU,EACT,OAAO,aAAY;GACjB,IAAI,SAAS,SAAS;IACpB,KAAK,eAAe,IAAI;KACtB,UAAU;KACV,SAAS,KAAK,UAAU,gBAAgB;KACxC,QAAQ,SAAS,aACb,KAAK,UACH,SAAS,YACT,SAAS,gBAGR,IAEF,SAAS,WAAW;IAC1B,CAAA;IACD,KAAK,OAAO,SAAS,CAAC,yBAAyB,CAAC;GAClD;EACF,EACD,CAAA;CACL;CAEA,WAAQ;EACN,KAAK,OAAO,SAAS,CAAC,yBAAyB,CAAC;CAClD;CA1KW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAgB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAhB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAgB,cAAA;EAAA,UAAA;EAAA,WA5IhB,CAAC,cAAc;EAAC,UAAA;EAAA,UACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyIT,UAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MApJC;IAAa,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACb;IAAkB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAClB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;IAAiB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACjB;IAAgB,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAChB;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACf;GAAW;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA,CAAA,eAAA;IAAA,UAAA,CAAA,SAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAA,GAAA;IAAA,UAAA;IAAA,QAAA,CAAA,eAAA;IAAA,SAAA,CAAA,UAAA;IAAA,UAAA,CAAA,QAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACX;IAAS,UAAA;IAAA,QAAA,CAAA,WAAA;IAAA,UAAA,CAAA,WAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MACT;IAAa,MAAA;GAAA;EAAA;CAAA,CAAA;;AA8IJ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAgB,YAAA,CAAA;EAzJ5B,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS;IACP;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACD;GACD,WAAW,CAAC,cAAc;GAC1B,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0IX,CAAA"}