Skip to content

Commit 97011bd

Browse files
feat(global-header): adding localization support for config string (#1447)
* feat(global-header): adding localization for config string Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * adding locale upport for profile Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * adding changeset and api report Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * updating api report Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * updting translateWithFallback Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * updating defaultMountPoints Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * fixing yarn prettier Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * removing comment Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * updating support Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> * updating api report Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com> --------- Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
1 parent 4142deb commit 97011bd

File tree

13 files changed

+146
-51
lines changed

13 files changed

+146
-51
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-global-header': minor
3+
---
4+
5+
Adding translation support for the string coming through configuration

workspaces/global-header/plugins/global-header/app-config.dynamic.yaml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,39 @@
22
dynamicPlugins:
33
frontend:
44
red-hat-developer-hub.backstage-plugin-global-header:
5+
translationResources:
6+
- importName: globalHeaderTranslations
7+
ref: globalHeaderTranslationRef
58
mountPoints:
69
- mountPoint: application/header
710
importName: GlobalHeader
811
config:
912
position: above-sidebar # above-main-content | above-sidebar
10-
1113
- mountPoint: global.header/component
1214
importName: CompanyLogo
1315
config:
1416
priority: 200
1517
props:
1618
to: '/'
17-
1819
- mountPoint: global.header/component
1920
importName: SearchComponent
2021
config:
2122
priority: 100
22-
2323
- mountPoint: global.header/component
2424
importName: Spacer
2525
config:
2626
priority: 99
2727
props:
2828
growFactor: 0
29-
3029
- mountPoint: global.header/component
3130
importName: HeaderIconButton
3231
config:
3332
priority: 90
3433
props:
35-
title: Create...
34+
title: Self-service
35+
titleKey: create.title
3636
icon: add
3737
to: create
38-
3938
- mountPoint: global.header/component
4039
importName: StarredDropdown
4140
config:
@@ -53,6 +52,7 @@ dynamicPlugins:
5352
priority: 150
5453
props:
5554
title: Developer Hub
55+
titleKey: applicationLauncher.developerHub
5656
icon: developerHub
5757
link: https://docs.redhat.com/en/documentation/red_hat_developer_hub
5858

@@ -63,6 +63,7 @@ dynamicPlugins:
6363
priority: 100
6464
props:
6565
title: RHDH Local
66+
titleKey: applicationLauncher.rhdhLocal
6667
icon: developerHub
6768
link: https://github.com/redhat-developer/rhdh-local
6869

@@ -80,26 +81,32 @@ dynamicPlugins:
8081
importName: NotificationButton
8182
config:
8283
priority: 70
83-
8484
- mountPoint: global.header/component
8585
importName: Divider
8686
config:
8787
priority: 50
88-
8988
- mountPoint: global.header/component
9089
importName: ProfileDropdown
9190
config:
9291
priority: 10
93-
9492
- mountPoint: global.header/profile
9593
importName: MenuItemLink
9694
config:
9795
priority: 100
9896
props:
9997
title: Settings
98+
titleKey: profile.settings
10099
link: /settings
101100
icon: manageAccounts
102-
101+
- mountPoint: global.header/profile
102+
importName: MenuItemLink
103+
config:
104+
priority: 90
105+
props:
106+
title: My profile
107+
titleKey: profile.myProfile
108+
type: myProfile
109+
icon: account
103110
- mountPoint: global.header/profile
104111
importName: LogoutButton
105112
config:

workspaces/global-header/plugins/global-header/report.api.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ export const HeaderIcon: ({
179179
// @public (undocumented)
180180
export const HeaderIconButton: ({
181181
title,
182+
titleKey,
182183
icon,
183184
tooltip,
184185
color,
@@ -203,6 +204,8 @@ export interface HeaderIconButtonProps {
203204
// (undocumented)
204205
title: string;
205206
// (undocumented)
207+
titleKey?: string;
208+
// (undocumented)
206209
to: string;
207210
// (undocumented)
208211
tooltip?: string;
@@ -248,9 +251,13 @@ export interface MenuItemConfig {
248251
// (undocumented)
249252
label: string;
250253
// (undocumented)
254+
labelKey?: string;
255+
// (undocumented)
251256
link?: string;
252257
// (undocumented)
253258
subLabel?: string;
259+
// (undocumented)
260+
subLabelKey?: string;
254261
}
255262

256263
// @public
@@ -263,8 +270,12 @@ export interface MenuItemLinkProps {
263270
// (undocumented)
264271
subTitle?: string;
265272
// (undocumented)
273+
subTitleKey?: string;
274+
// (undocumented)
266275
title?: string;
267276
// (undocumented)
277+
titleKey?: string;
278+
// (undocumented)
268279
to: string;
269280
// (undocumented)
270281
tooltip?: string;
@@ -408,6 +419,8 @@ export interface SupportButtonProps {
408419
// (undocumented)
409420
title?: string;
410421
// (undocumented)
422+
titleKey?: string;
423+
// (undocumented)
411424
to?: string;
412425
// (undocumented)
413426
tooltip?: string;

workspaces/global-header/plugins/global-header/src/components/HeaderDropdownComponent/ApplicationLauncherDropdown.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export const ApplicationLauncherDropdown = () => {
4949
Component: mp.Component,
5050
icon: mp.config?.props?.icon,
5151
label: mp.config?.props?.title,
52+
labelKey: mp.config?.props?.titleKey,
5253
link: mp.config?.props?.link,
5354
external: mp.config?.props?.external ?? false,
5455
priority: mp.config?.priority ?? 0,

workspaces/global-header/plugins/global-header/src/components/HeaderDropdownComponent/MenuSection.tsx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ import { useTranslation } from '../../hooks/useTranslation';
3232
export interface MenuItemConfig {
3333
Component: ComponentType<MenuItemLinkProps | MenuItemProps | {}>;
3434
label: string;
35+
labelKey?: string;
3536
icon?: string;
3637
subLabel?: string;
38+
subLabelKey?: string;
3739
link?: string;
3840
}
3941

@@ -106,25 +108,32 @@ export const MenuSection: FC<MenuSectionConfig> = ({
106108
</MenuItem>
107109
)}
108110

109-
{items.map(({ icon, label, subLabel, link, Component }, index) => (
110-
<MenuItem
111-
key={`menu-item-${index.toString()}`}
112-
disableRipple
113-
disableTouchRipple
114-
onClick={handleClose}
115-
sx={{ py: 0.5 }}
116-
component={link ? Link : Fragment}
117-
to={link}
118-
>
119-
<Component
120-
icon={icon}
121-
to={link!}
122-
title={label}
123-
subTitle={subLabel}
111+
{items.map(
112+
(
113+
{ icon, label, labelKey, subLabel, subLabelKey, link, Component },
114+
index,
115+
) => (
116+
<MenuItem
117+
key={`menu-item-${index.toString()}`}
118+
disableRipple
119+
disableTouchRipple
124120
onClick={handleClose}
125-
/>
126-
</MenuItem>
127-
))}
121+
sx={{ py: 0.5 }}
122+
component={link ? Link : Fragment}
123+
to={link}
124+
>
125+
<Component
126+
icon={icon}
127+
to={link!}
128+
title={label}
129+
titleKey={labelKey}
130+
subTitle={subLabel}
131+
subTitleKey={subLabelKey}
132+
onClick={handleClose}
133+
/>
134+
</MenuItem>
135+
),
136+
)}
128137
{!hideDivider && <Divider sx={{ my: 0.5 }} />}
129138
</>
130139
);

workspaces/global-header/plugins/global-header/src/components/HeaderDropdownComponent/ProfileDropdown.test.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ jest.mock('../../hooks/useProfileDropdownMountPoints', () => {
4747
config: {
4848
props: {
4949
icon: 'manageAccounts',
50-
title: 'profile.settings',
50+
title: 'Settings',
51+
titleKey: 'profile.settings',
5152
link: '/settings',
5253
},
5354
priority: 200,
@@ -58,7 +59,8 @@ jest.mock('../../hooks/useProfileDropdownMountPoints', () => {
5859
config: {
5960
props: {
6061
icon: 'account',
61-
title: 'profile.myProfile',
62+
title: 'My profile',
63+
titleKey: 'profile.myProfile',
6264
type: 'myProfile',
6365
},
6466
priority: 150,

workspaces/global-header/plugins/global-header/src/components/HeaderDropdownComponent/ProfileDropdown.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { HeaderDropdownComponent } from './HeaderDropdownComponent';
3232
import { useProfileDropdownMountPoints } from '../../hooks/useProfileDropdownMountPoints';
3333
import { useDropdownManager } from '../../hooks';
3434
import { useTranslation } from '../../hooks/useTranslation';
35+
import { translateWithFallback } from '../../utils/translationUtils';
3536

3637
/**
3738
* @public
@@ -120,6 +121,7 @@ export const ProfileDropdown = ({ layout }: ProfileDropdownProps) => {
120121
.map(mp => {
121122
const {
122123
title = '',
124+
titleKey = '',
123125
icon = '',
124126
link: staticLink = '',
125127
type = '',
@@ -137,10 +139,7 @@ export const ProfileDropdown = ({ layout }: ProfileDropdownProps) => {
137139
return null;
138140
}
139141

140-
// Check if title looks like a translation key (contains dots)
141-
const translatedTitle = title?.includes('.')
142-
? t(title as any, {}) || title // Fallback to original title if translation fails
143-
: title;
142+
const translatedTitle = translateWithFallback(t, titleKey, title);
144143

145144
return {
146145
Component: mp.Component,

workspaces/global-header/plugins/global-header/src/components/HeaderIconButton/HeaderIconButton.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ import IconButton, { IconButtonProps } from '@mui/material/IconButton';
2222
import Tooltip from '@mui/material/Tooltip';
2323

2424
import { HeaderIcon } from '../HeaderIcon/HeaderIcon';
25+
import { useTranslation } from '../../hooks/useTranslation';
26+
import { translateWithFallback } from '../../utils/translationUtils';
2527

2628
/**
2729
* @public
2830
*/
2931
export interface HeaderIconButtonProps {
3032
title: string;
33+
titleKey?: string;
3134
icon: string;
3235
tooltip?: string;
3336
color?: 'inherit' | 'primary' | 'secondary' | 'default';
@@ -44,6 +47,7 @@ const Link = (props: any) => (
4447

4548
export const HeaderIconButton = ({
4649
title,
50+
titleKey,
4751
icon,
4852
tooltip,
4953
color = 'inherit',
@@ -52,7 +56,9 @@ export const HeaderIconButton = ({
5256
to,
5357
layout,
5458
}: HeaderIconButtonProps) => {
55-
if (!title) {
59+
const { t } = useTranslation();
60+
const displayTitle = translateWithFallback(t, titleKey, title);
61+
if (!displayTitle) {
5662
// eslint-disable-next-line no-console
5763
console.warn('HeaderIconButton has no title:', { icon, to });
5864
}
@@ -61,13 +67,13 @@ export const HeaderIconButton = ({
6167

6268
return (
6369
<Box sx={layout}>
64-
<Tooltip title={tooltip ?? title}>
70+
<Tooltip title={tooltip ?? displayTitle}>
6571
<div>
6672
<IconButton
6773
LinkComponent={Link}
6874
color={color}
6975
size={size}
70-
aria-label={ariaLabel ?? title}
76+
aria-label={ariaLabel ?? displayTitle}
7177
{...linkProps} // to={to} isn't supported
7278
>
7379
<HeaderIcon icon={icon} size={size} />

workspaces/global-header/plugins/global-header/src/components/MenuItemLink/MenuItemLink.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import Tooltip from '@mui/material/Tooltip';
1818
import { useTranslation } from '../../hooks/useTranslation';
1919
import { MenuItemLinkContent } from './MenuItemLinkContent';
20+
import { translateWithFallback } from '../../utils/translationUtils';
2021

2122
/**
2223
* Header Icon Button properties
@@ -25,15 +26,19 @@ import { MenuItemLinkContent } from './MenuItemLinkContent';
2526
export interface MenuItemLinkProps {
2627
to: string;
2728
title?: string;
29+
titleKey?: string;
2830
subTitle?: string;
31+
subTitleKey?: string;
2932
icon?: string;
3033
tooltip?: string;
3134
}
3235

3336
export const MenuItemLink = ({
3437
to,
3538
title,
39+
titleKey,
3640
subTitle,
41+
subTitleKey,
3742
icon,
3843
tooltip,
3944
}: MenuItemLinkProps) => {
@@ -42,16 +47,14 @@ export const MenuItemLink = ({
4247
to && (to.startsWith('http://') || to.startsWith('https://')),
4348
);
4449

45-
// Check if title looks like a translation key (contains dots)
46-
const translatedTitle = title?.includes('.')
47-
? t(title as any, {}) || title // Fallback to original title if translation fails
48-
: title;
50+
const translatedTitle = translateWithFallback(t, titleKey, title);
51+
const translatedSubTitle = translateWithFallback(t, subTitleKey, subTitle);
4952

5053
const headerLinkContent = () => (
5154
<MenuItemLinkContent
5255
icon={icon}
5356
label={translatedTitle}
54-
subLabel={subTitle}
57+
subLabel={translatedSubTitle}
5558
isExternalLink={isExternalLink}
5659
/>
5760
);

0 commit comments

Comments
 (0)