Skip to content

Commit e52691b

Browse files
WEB-398 fix(breadcrumb):update breadcrumb headings on language change (#2954)
1 parent 53a238a commit e52691b

File tree

1 file changed

+137
-127
lines changed

1 file changed

+137
-127
lines changed
Lines changed: 137 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/** Angular Imports */
2-
import { Component, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core';
2+
import { Component, TemplateRef, ElementRef, ViewChild, AfterViewInit, OnDestroy, inject } from '@angular/core';
33
import { ActivatedRoute, Router, NavigationEnd, Data, RouterLink } from '@angular/router';
44

55
/** rxjs Imports */
6-
import { filter } from 'rxjs/operators';
6+
import { filter, takeUntil } from 'rxjs/operators';
7+
import { merge, Subject } from 'rxjs';
78

89
/** Custom Model */
910
import { Breadcrumb } from './breadcrumb.model';
@@ -54,12 +55,13 @@ const routeAddBreadcrumbLink = 'addBreadcrumbLink';
5455
...STANDALONE_SHARED_IMPORTS
5556
]
5657
})
57-
export class BreadcrumbComponent implements AfterViewInit {
58+
export class BreadcrumbComponent implements AfterViewInit, OnDestroy {
5859
private activatedRoute = inject(ActivatedRoute);
5960
private router = inject(Router);
6061
private configurationWizardService = inject(ConfigurationWizardService);
6162
private popoverService = inject(PopoverService);
6263
private translateService = inject(TranslateService);
64+
private destroy$ = new Subject<void>();
6365

6466
/** Array of breadcrumbs. */
6567
breadcrumbs: Breadcrumb[];
@@ -85,142 +87,130 @@ export class BreadcrumbComponent implements AfterViewInit {
8587
generateBreadcrumbs() {
8688
const onNavigationEnd = this.router.events.pipe(filter((event) => event instanceof NavigationEnd));
8789

88-
onNavigationEnd.subscribe(() => {
89-
this.breadcrumbs = [];
90-
let currentRoute = this.activatedRoute.root;
91-
let currentUrl = '';
90+
// Merge navigation events with language change events to regenerate breadcrumbs when language changes
91+
merge(onNavigationEnd, this.translateService.onLangChange)
92+
.pipe(takeUntil(this.destroy$))
93+
.subscribe(() => {
94+
this.breadcrumbs = [];
95+
let currentRoute = this.activatedRoute.root;
96+
let currentUrl = '';
9297

93-
while (currentRoute.children.length > 0) {
94-
const childrenRoutes = currentRoute.children;
95-
let breadcrumbLabel: any;
96-
let url: any;
98+
while (currentRoute.children.length > 0) {
99+
const childrenRoutes = currentRoute.children;
100+
let breadcrumbLabel: any;
101+
let url: any;
97102

98-
childrenRoutes.forEach((route) => {
99-
currentRoute = route;
100-
breadcrumbLabel = false;
103+
childrenRoutes.forEach((route) => {
104+
currentRoute = route;
105+
breadcrumbLabel = false;
101106

102-
if (route.outlet !== 'primary') {
103-
return;
104-
}
107+
if (route.outlet !== 'primary') {
108+
return;
109+
}
105110

106-
const routeURL = route.snapshot.url.map((segment) => segment.path).join('/');
107-
currentUrl += `/${routeURL}`;
111+
const routeURL = route.snapshot.url.map((segment) => segment.path).join('/');
112+
currentUrl += `/${routeURL}`;
108113

109-
if (currentUrl === '/') {
110-
breadcrumbLabel = 'Home';
111-
}
114+
if (currentUrl === '/') {
115+
breadcrumbLabel = 'Home';
116+
}
112117

113-
const hasData = route.routeConfig && route.routeConfig.data;
118+
const hasData = route.routeConfig && route.routeConfig.data;
114119

115-
if (hasData) {
116-
if (
117-
route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) &&
118-
route.snapshot.data[routeResolveBreadcrumb]
119-
) {
120-
breadcrumbLabel = route.snapshot.data;
121-
route.snapshot.data[routeResolveBreadcrumb].forEach((property: any) => {
122-
breadcrumbLabel = breadcrumbLabel[property];
123-
});
124-
} else if (
125-
route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) &&
126-
route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])
127-
) {
128-
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
129-
const routeData: Data = route.snapshot.data;
130-
if (routeData.breadcrumb === 'Clients') {
131-
breadcrumbLabel = this.printableValue(routeData.clientViewData.displayName);
132-
currentUrl += `/general`;
133-
} else if (routeData.breadcrumb === 'Groups') {
134-
breadcrumbLabel = routeData.groupViewData.name;
135-
} else if (routeData.breadcrumb === 'Centers') {
136-
breadcrumbLabel = routeData.centerViewData.name;
137-
} else if (routeData.breadcrumb === 'Loans') {
138-
breadcrumbLabel =
139-
this.printableValue(routeData.loanDetailsData.loanProductName) +
140-
' (' +
141-
routeData.loanDetailsData.accountNo +
142-
')';
143-
} else if (routeData.breadcrumb === 'Savings') {
144-
const savingsProductName = routeData.savingsAccountData?.savingsProductName ?? '';
145-
const accountNo = routeData.savingsAccountData?.accountNo ?? '';
146-
breadcrumbLabel = this.printableValue(savingsProductName) + (accountNo ? ' (' + accountNo + ')' : '');
147-
} else if (routeData.breadcrumb === 'Fixed Deposits') {
148-
breadcrumbLabel =
149-
this.printableValue(routeData.fixedDepositsAccountData.depositProductName) +
150-
' (' +
151-
routeData.fixedDepositsAccountData.accountNo +
152-
')';
153-
} else if (routeData.breadcrumb === 'Loan Products') {
154-
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
155-
} else if (routeData.breadcrumb === 'Charges') {
156-
breadcrumbLabel = routeData.loansAccountCharge.name;
157-
} else if (routeData.breadcrumb === 'Saving Products') {
158-
breadcrumbLabel = routeData.savingProduct.name;
159-
} else if (routeData.breadcrumb === 'Share Products') {
160-
breadcrumbLabel = routeData.shareProduct.name;
161-
} else if (routeData.breadcrumb === 'Fixed Deposit Products') {
162-
breadcrumbLabel = routeData.fixedDepositProduct.name;
163-
} else if (routeData.breadcrumb === 'Recurring Deposit Products') {
164-
breadcrumbLabel = routeData.recurringDepositProduct.name;
165-
} else if (routeData.breadcrumb === 'Floating Rates') {
166-
breadcrumbLabel = routeData.floatingRate.name;
167-
} else if (routeData.breadcrumb === 'Tax Components') {
168-
breadcrumbLabel = routeData.taxComponent.name;
169-
} else if (routeData.breadcrumb === 'Tax Groups') {
170-
breadcrumbLabel = routeData.taxGroup.name;
171-
}
172-
173-
// Check if the breadcrumbLabel is an action name that should be translated using labels.menus
174-
// This handles action names from route parameters for Savings, Loans, Shares, Fixed Deposits, and Recurring Deposits accounts
120+
if (hasData) {
175121
if (
176-
breadcrumbLabel &&
177-
(routeData.breadcrumb === 'Savings Account Actions' ||
178-
routeData.breadcrumb === 'Loan Account Actions' ||
179-
routeData.breadcrumb === 'Shares Account Actions' ||
180-
routeData.breadcrumb === 'Actions' ||
181-
routeData.breadcrumb === 'action' ||
182-
routeData.title === 'Fixed Deposits Account Actions' ||
183-
routeData.title === 'Recurring Deposits Account Actions')
122+
route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) &&
123+
route.snapshot.data[routeResolveBreadcrumb]
124+
) {
125+
breadcrumbLabel = route.snapshot.data;
126+
route.snapshot.data[routeResolveBreadcrumb].forEach((property: any) => {
127+
breadcrumbLabel = breadcrumbLabel[property];
128+
});
129+
} else if (
130+
route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) &&
131+
route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])
184132
) {
185-
const menuKey = 'labels.menus.' + breadcrumbLabel;
186-
const menuTranslation = this.translateService.instant(menuKey);
187-
if (menuTranslation !== menuKey) {
188-
breadcrumbLabel = menuTranslation;
133+
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
134+
const routeData: Data = route.snapshot.data;
135+
if (routeData.breadcrumb === 'Clients') {
136+
breadcrumbLabel = this.printableValue(routeData.clientViewData.displayName);
137+
currentUrl += `/general`;
138+
} else if (routeData.breadcrumb === 'Groups') {
139+
breadcrumbLabel = routeData.groupViewData.name;
140+
} else if (routeData.breadcrumb === 'Centers') {
141+
breadcrumbLabel = routeData.centerViewData.name;
142+
} else if (routeData.breadcrumb === 'Loans') {
143+
breadcrumbLabel =
144+
this.printableValue(routeData.loanDetailsData.loanProductName) +
145+
' (' +
146+
routeData.loanDetailsData.accountNo +
147+
')';
148+
} else if (routeData.breadcrumb === 'Savings') {
149+
const savingsProductName = routeData.savingsAccountData?.savingsProductName ?? '';
150+
const accountNo = routeData.savingsAccountData?.accountNo ?? '';
151+
breadcrumbLabel = this.printableValue(savingsProductName) + (accountNo ? ' (' + accountNo + ')' : '');
152+
} else if (routeData.breadcrumb === 'Fixed Deposits') {
153+
breadcrumbLabel =
154+
this.printableValue(routeData.fixedDepositsAccountData.depositProductName) +
155+
' (' +
156+
routeData.fixedDepositsAccountData.accountNo +
157+
')';
158+
} else if (routeData.breadcrumb === 'Loan Products') {
159+
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
160+
} else if (routeData.breadcrumb === 'Charges') {
161+
breadcrumbLabel = routeData.loansAccountCharge.name;
162+
} else if (routeData.breadcrumb === 'Saving Products') {
163+
breadcrumbLabel = routeData.savingProduct.name;
164+
} else if (routeData.breadcrumb === 'Share Products') {
165+
breadcrumbLabel = routeData.shareProduct.name;
166+
} else if (routeData.breadcrumb === 'Fixed Deposit Products') {
167+
breadcrumbLabel = routeData.fixedDepositProduct.name;
168+
} else if (routeData.breadcrumb === 'Recurring Deposit Products') {
169+
breadcrumbLabel = routeData.recurringDepositProduct.name;
170+
} else if (routeData.breadcrumb === 'Floating Rates') {
171+
breadcrumbLabel = routeData.floatingRate.name;
172+
} else if (routeData.breadcrumb === 'Tax Components') {
173+
breadcrumbLabel = routeData.taxComponent.name;
174+
} else if (routeData.breadcrumb === 'Tax Groups') {
175+
breadcrumbLabel = routeData.taxGroup.name;
189176
}
177+
178+
// For action names, keep the original name and let getTranslate() handle translation dynamically
179+
// This ensures breadcrumbs update when language changes without requiring navigation
180+
// The getTranslate() method will check both labels.text.* and labels.menus.* for translations
181+
} else if (route.snapshot.data.hasOwnProperty(routeDataBreadcrumb)) {
182+
breadcrumbLabel = route.snapshot.data[routeDataBreadcrumb];
190183
}
191-
} else if (route.snapshot.data.hasOwnProperty(routeDataBreadcrumb)) {
192-
breadcrumbLabel = route.snapshot.data[routeDataBreadcrumb];
193-
}
194184

195-
if (route.snapshot.data.hasOwnProperty(routeAddBreadcrumbLink)) {
196-
url = route.snapshot.data[routeAddBreadcrumbLink];
197-
} else {
198-
url = currentUrl;
185+
if (route.snapshot.data.hasOwnProperty(routeAddBreadcrumbLink)) {
186+
url = route.snapshot.data[routeAddBreadcrumbLink];
187+
} else {
188+
url = currentUrl;
189+
}
199190
}
200-
}
201-
if (url !== undefined) {
202-
if (url.length > 8 && url.search(`/clients/`) > 0) {
203-
const replaceGeneral = `/general/`;
204-
let currentUrlTemp = url.replace(replaceGeneral, `/`);
205-
currentUrlTemp = currentUrlTemp.replace(`//`, `/`);
206-
currentUrlTemp += `/general`;
207-
const replaceDoubleSlash = `/general/general`;
208-
currentUrlTemp = currentUrlTemp.replace(replaceDoubleSlash, `/general`);
209-
url = currentUrlTemp;
191+
if (url !== undefined) {
192+
if (url.length > 8 && url.search(`/clients/`) > 0) {
193+
const replaceGeneral = `/general/`;
194+
let currentUrlTemp = url.replace(replaceGeneral, `/`);
195+
currentUrlTemp = currentUrlTemp.replace(`//`, `/`);
196+
currentUrlTemp += `/general`;
197+
const replaceDoubleSlash = `/general/general`;
198+
currentUrlTemp = currentUrlTemp.replace(replaceDoubleSlash, `/general`);
199+
url = currentUrlTemp;
200+
}
210201
}
211-
}
212202

213-
const breadcrumb: Breadcrumb = {
214-
label: breadcrumbLabel,
215-
url: url
216-
};
203+
const breadcrumb: Breadcrumb = {
204+
label: breadcrumbLabel,
205+
url: url
206+
};
217207

218-
if (breadcrumbLabel) {
219-
this.breadcrumbs.push(breadcrumb);
220-
}
221-
});
222-
}
223-
});
208+
if (breadcrumbLabel) {
209+
this.breadcrumbs.push(breadcrumb);
210+
}
211+
});
212+
}
213+
});
224214
}
225215

226216
printableValue(value: string): string {
@@ -280,9 +270,29 @@ export class BreadcrumbComponent implements AfterViewInit {
280270
}
281271

282272
getTranslate(text: string): any {
283-
const key: string = 'labels.text.' + text;
284-
const translation = this.translateService.instant(key);
285-
const result = translation !== key ? translation : text;
286-
return result;
273+
// First try labels.text.* (for static breadcrumb labels)
274+
let key: string = 'labels.text.' + text;
275+
let translation = this.translateService.instant(key);
276+
if (translation !== key) {
277+
return translation;
278+
}
279+
280+
// Then try labels.menus.* (for action names like "View Guarantors")
281+
key = 'labels.menus.' + text;
282+
translation = this.translateService.instant(key);
283+
if (translation !== key) {
284+
return translation;
285+
}
286+
287+
// If no translation found, return the original text
288+
return text;
289+
}
290+
291+
/**
292+
* Clean up subscriptions on component destroy.
293+
*/
294+
ngOnDestroy(): void {
295+
this.destroy$.next();
296+
this.destroy$.complete();
287297
}
288298
}

0 commit comments

Comments
 (0)