Merge pull request #31565 from Eswaraiahsapram/add-missing-i18n-to-catalog-plugin

fix: add missing i18n support for catalog plugin
This commit is contained in:
Patrik Oldsberg
2026-02-08 10:53:03 +01:00
committed by GitHub
12 changed files with 81 additions and 23 deletions
+11 -1
View File
@@ -43,11 +43,16 @@ export const catalogTranslationRef: TranslationRef<
readonly 'indexPage.title': '{{orgName}} Catalog';
readonly 'indexPage.createButtonTitle': 'Create';
readonly 'indexPage.supportButtonContent': 'All your software catalog entities';
readonly 'entityPage.notFoundMessage': 'There is no {{kind}} with the requested {{link}}.';
readonly 'entityPage.notFoundLinkText': 'kind, namespace, and name';
readonly 'aboutCard.title': 'About';
readonly 'aboutCard.unknown': 'unknown';
readonly 'aboutCard.refreshButtonTitle': 'Schedule entity refresh';
readonly 'aboutCard.editButtonTitle': 'Edit Metadata';
readonly 'aboutCard.editButtonAriaLabel': 'Edit';
readonly 'aboutCard.createSimilarButtonTitle': 'Create something similar';
readonly 'aboutCard.refreshScheduledMessage': 'Refresh scheduled';
readonly 'aboutCard.refreshButtonAriaLabel': 'Refresh';
readonly 'aboutCard.launchTemplate': 'Launch Template';
readonly 'aboutCard.viewTechdocs': 'View TechDocs';
readonly 'aboutCard.viewSource': 'View Source';
@@ -66,8 +71,11 @@ export const catalogTranslationRef: TranslationRef<
readonly 'aboutCard.tagsField.value': 'No Tags';
readonly 'aboutCard.tagsField.label': 'Tags';
readonly 'aboutCard.targetsField.label': 'Targets';
readonly 'searchResultItem.type': 'Type';
readonly 'searchResultItem.kind': 'Kind';
readonly 'searchResultItem.lifecycle': 'Lifecycle';
readonly 'searchResultItem.Owner': 'Owner';
readonly 'searchResultItem.owner': 'Owner';
readonly 'catalogTable.allFilters': 'All';
readonly 'catalogTable.warningPanelTitle': 'Could not fetch catalog entities.';
readonly 'catalogTable.viewActionTitle': 'View';
readonly 'catalogTable.editActionTitle': 'Edit';
@@ -84,6 +92,7 @@ export const catalogTranslationRef: TranslationRef<
readonly 'entityContextMenu.inspectMenuTitle': 'Inspect entity';
readonly 'entityContextMenu.copyURLMenuTitle': 'Copy entity URL';
readonly 'entityContextMenu.unregisterMenuTitle': 'Unregister entity';
readonly 'entityContextMenu.moreButtonAriaLabel': 'more';
readonly 'entityLabelsCard.title': 'Labels';
readonly 'entityLabelsCard.emptyDescription': 'No labels defined for this entity. You can add labels to your entity YAML as shown in the highlighted example below:';
readonly 'entityLabelsCard.readMoreButtonTitle': 'Read more';
@@ -96,6 +105,7 @@ export const catalogTranslationRef: TranslationRef<
readonly 'entityNotFound.title': 'Entity was not found';
readonly 'entityNotFound.description': 'Want to help us build this? Check out our Getting Started documentation.';
readonly 'entityNotFound.docButtonTitle': 'DOCS';
readonly 'entityTabs.tabsAriaLabel': 'Tabs';
readonly entityProcessingErrorsDescription: 'The error below originates from';
readonly entityRelationWarningDescription: "This entity has relations to other entities, which can't be found in the catalog.\n Entities not found are: ";
readonly 'hasComponentsCard.title': 'Has components';
@@ -180,11 +180,14 @@ export const EntityLayout = (props: EntityLayoutProps) => {
NotFoundComponent
) : (
<WarningPanel title={t('entityLabels.warningPanelTitle')}>
There is no {kind} with the requested{' '}
<Link to="https://backstage.io/docs/features/software-catalog/references">
kind, namespace, and name
</Link>
.
{t('entityPage.notFoundMessage', {
kind,
link: (
<Link to="https://backstage.io/docs/features/software-catalog/references">
{t('entityPage.notFoundLinkText')}
</Link>
),
})}
</WarningPanel>
)}
</Content>
@@ -18,9 +18,12 @@ import { ReactElement, useMemo } from 'react';
import Box from '@material-ui/core/Box';
import Tabs from '@material-ui/core/Tabs';
import { makeStyles } from '@material-ui/core/styles';
import { EntityTabsGroup } from './EntityTabsGroup';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { EntityContentGroupDefinitions } from '@backstage/plugin-catalog-react/alpha';
import { EntityTabsGroup } from './EntityTabsGroup';
import { catalogTranslationRef } from '../../translation';
/** @public */
export type HeaderTabsClassKey =
| 'tabsWrapper'
@@ -81,6 +84,7 @@ type EntityTabsListProps = {
export function EntityTabsList(props: EntityTabsListProps) {
const styles = useStyles();
const { t } = useTranslationRef(catalogTranslationRef);
const { tabs: items, selectedIndex = 0, showIcons, groupDefinitions } = props;
@@ -108,7 +112,7 @@ export function EntityTabsList(props: EntityTabsListProps) {
textColor="inherit"
variant="scrollable"
scrollButtons="auto"
aria-label="tabs"
aria-label={t('entityTabs.tabsAriaLabel')}
value={selectedItem?.group ?? selectedItem?.id}
>
{Object.entries(groups).map(([id, tabGroup]) => (
+15 -1
View File
@@ -25,15 +25,22 @@ export const catalogTranslationRef = createTranslationRef({
createButtonTitle: 'Create',
supportButtonContent: 'All your software catalog entities',
},
entityPage: {
notFoundMessage: 'There is no {{kind}} with the requested {{link}}.',
notFoundLinkText: 'kind, namespace, and name',
},
aboutCard: {
title: 'About',
refreshButtonTitle: 'Schedule entity refresh',
editButtonTitle: 'Edit Metadata',
editButtonAriaLabel: 'Edit',
createSimilarButtonTitle: 'Create something similar',
refreshScheduledMessage: 'Refresh scheduled',
refreshButtonAriaLabel: 'Refresh',
launchTemplate: 'Launch Template',
viewTechdocs: 'View TechDocs',
viewSource: 'View Source',
unknown: 'unknown',
descriptionField: {
label: 'Description',
value: 'No description',
@@ -69,8 +76,10 @@ export const catalogTranslationRef = createTranslationRef({
},
},
searchResultItem: {
kind: 'Kind',
type: 'Type',
lifecycle: 'Lifecycle',
Owner: 'Owner',
owner: 'Owner',
},
catalogTable: {
warningPanelTitle: 'Could not fetch catalog entities.',
@@ -78,6 +87,7 @@ export const catalogTranslationRef = createTranslationRef({
editActionTitle: 'Edit',
starActionTitle: 'Add to favorites',
unStarActionTitle: 'Remove from favorites',
allFilters: 'All',
},
dependencyOfComponentsCard: {
title: 'Dependency of components',
@@ -97,6 +107,7 @@ export const catalogTranslationRef = createTranslationRef({
inspectMenuTitle: 'Inspect entity',
copyURLMenuTitle: 'Copy entity URL',
unregisterMenuTitle: 'Unregister entity',
moreButtonAriaLabel: 'more',
},
entityLabelsCard: {
title: 'Labels',
@@ -121,6 +132,9 @@ export const catalogTranslationRef = createTranslationRef({
'Want to help us build this? Check out our Getting Started documentation.',
docButtonTitle: 'DOCS',
},
entityTabs: {
tabsAriaLabel: 'Tabs',
},
deleteEntity: {
dialogTitle: 'Are you sure you want to delete this entity?',
deleteButtonTitle: 'Delete',
@@ -241,7 +241,7 @@ export function InternalAboutCard(props: InternalAboutCardProps) {
<>
{allowRefresh && canRefresh && (
<IconButton
aria-label="Refresh"
aria-label={t('aboutCard.refreshButtonAriaLabel')}
title={t('aboutCard.refreshButtonTitle')}
onClick={refreshEntity}
>
@@ -250,7 +250,7 @@ export function InternalAboutCard(props: InternalAboutCardProps) {
)}
<IconButton
component={Link}
aria-label="Edit"
aria-label={t('aboutCard.editButtonAriaLabel')}
disabled={!entityMetadataEditUrl}
title={t('aboutCard.editButtonTitle')}
to={entityMetadataEditUrl ?? '#'}
@@ -225,7 +225,7 @@ export function AboutContent(props: AboutContentProps) {
text: target,
href: getLocationTargetHref(
target,
(entity?.spec?.type || 'unknown') as string,
(entity?.spec?.type || t('aboutCard.unknown')) as string,
entitySourceLocation!,
),
}))}
@@ -19,6 +19,8 @@ import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import { ReactNode } from 'react';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { catalogTranslationRef } from '../../alpha/translation';
const useStyles = makeStyles(theme => ({
value: {
@@ -55,6 +57,7 @@ export interface AboutFieldProps {
export function AboutField(props: AboutFieldProps) {
const { label, value, gridSizes, children, className } = props;
const classes = useStyles();
const { t } = useTranslationRef(catalogTranslationRef);
const childElements = useElementFilter(children, c => c.getElements());
@@ -64,7 +67,7 @@ export function AboutField(props: AboutFieldProps) {
childElements
) : (
<Typography variant="body2" className={classes.value}>
{value || `unknown`}
{value || t('aboutCard.unknown')}
</Typography>
);
return (
@@ -127,8 +127,18 @@ export function CatalogSearchResultListItem(
}
/>
<Box>
{result.kind && <Chip label={`Kind: ${result.kind}`} size="small" />}
{result.type && <Chip label={`Type: ${result.type}`} size="small" />}
{result.kind && (
<Chip
label={`${t('searchResultItem.kind')}: ${result.kind}`}
size="small"
/>
)}
{result.type && (
<Chip
label={`${t('searchResultItem.type')}: ${result.type}`}
size="small"
/>
)}
{result.lifecycle && (
<Chip
label={`${t('searchResultItem.lifecycle')}: ${result.lifecycle}`}
@@ -137,7 +147,7 @@ export function CatalogSearchResultListItem(
)}
{result.owner && (
<Chip
label={`${t('searchResultItem.Owner')}: ${result.owner}`}
label={`${t('searchResultItem.owner')}: ${result.owner}`}
size="small"
/>
)}
@@ -186,7 +186,9 @@ export const CatalogTable = (props: CatalogTableProps) => {
const currentType = filters.type?.value || '';
const currentCount = typeof totalItems === 'number' ? `(${totalItems})` : '';
// TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar
const titlePreamble = capitalize(filters.user?.value ?? 'all');
const titlePreamble = capitalize(
filters.user?.value ?? t('catalogTable.allFilters'),
);
const title =
props.title ||
[titlePreamble, currentType, pluralize(currentKind), currentCount]
@@ -161,7 +161,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) {
<>
<Tooltip title={t('entityContextMenu.moreButtonTitle')} arrow>
<IconButton
aria-label="more"
aria-label={t('entityContextMenu.moreButtonAriaLabel')}
aria-controls="long-menu"
aria-haspopup="true"
aria-expanded={!!anchorEl}
@@ -389,11 +389,14 @@ export const EntityLayout = (props: EntityLayoutProps) => {
NotFoundComponent
) : (
<WarningPanel title={t('entityLabels.warningPanelTitle')}>
There is no {kind} with the requested{' '}
<Link to="https://backstage.io/docs/features/software-catalog/references">
kind, namespace, and name
</Link>
.
{t('entityPage.notFoundMessage', {
kind,
link: (
<Link to="https://backstage.io/docs/features/software-catalog/references">
{t('entityPage.notFoundLinkText')}
</Link>
),
})}
</WarningPanel>
)}
</Content>