feat: home plugin support i18n
Signed-off-by: mario ma <mario.ma.node@gmail.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-home-react': patch
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
Home plugin support i18n
|
||||
@@ -44,6 +44,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/core-components": "workspace:^",
|
||||
"@backstage/core-plugin-api": "workspace:^",
|
||||
"@backstage/frontend-plugin-api": "workspace:^",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@rjsf/utils": "5.23.2"
|
||||
|
||||
@@ -9,6 +9,7 @@ import { JSX as JSX_3 } from 'react';
|
||||
import { Overrides } from '@material-ui/core/styles/overrides';
|
||||
import { RJSFSchema } from '@rjsf/utils';
|
||||
import { StyleRules } from '@material-ui/core/styles/withStyles';
|
||||
import { TranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { UiSchema } from '@rjsf/utils';
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -81,6 +82,16 @@ export function createCardExtension<T>(options: {
|
||||
settings?: CardSettings;
|
||||
}): Extension<(props: CardExtensionProps<T>) => JSX_2.Element>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const homeReactTranslationRef: TranslationRef<
|
||||
'home-react',
|
||||
{
|
||||
readonly 'settingsModal.title': 'Settings';
|
||||
readonly 'settingsModal.closeButtonTitle': 'Close';
|
||||
readonly 'cardExtension.settingsButtonTitle': 'Settings';
|
||||
}
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type PluginHomeComponentsNameToClassKey = {
|
||||
PluginHomeContentModal: PluginHomeContentModalClassKey;
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import { homeReactTranslationRef } from '../translation';
|
||||
|
||||
/** @public */
|
||||
export const SettingsModal = (props: {
|
||||
@@ -28,16 +30,18 @@ export const SettingsModal = (props: {
|
||||
children: JSX.Element;
|
||||
}) => {
|
||||
const { open, close, componentName, children } = props;
|
||||
|
||||
const { t } = useTranslationRef(homeReactTranslationRef);
|
||||
return (
|
||||
<Dialog open={open} onClose={() => close()}>
|
||||
<DialogTitle>
|
||||
{componentName ? `Settings - ${componentName}` : 'Settings'}
|
||||
{componentName
|
||||
? `${t('settingsModal.title')} - ${componentName}`
|
||||
: t('settingsModal.title')}
|
||||
</DialogTitle>
|
||||
<DialogContent>{children}</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => close()} color="primary" variant="contained">
|
||||
Close
|
||||
{t('settingsModal.closeButtonTitle')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
@@ -21,6 +21,8 @@ import { InfoCard } from '@backstage/core-components';
|
||||
import { SettingsModal } from './components';
|
||||
import { createReactExtension, useApp } from '@backstage/core-plugin-api';
|
||||
import { RJSFSchema, UiSchema } from '@rjsf/utils';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeReactTranslationRef } from './translation';
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -133,6 +135,7 @@ function CardExtension<T>(props: CardExtensionComponentProps<T>) {
|
||||
const app = useApp();
|
||||
const { Progress } = app.getComponents();
|
||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||
const { t } = useTranslationRef(homeReactTranslationRef);
|
||||
|
||||
if (Renderer) {
|
||||
return (
|
||||
@@ -158,7 +161,9 @@ function CardExtension<T>(props: CardExtensionComponentProps<T>) {
|
||||
? {
|
||||
action: (
|
||||
<IconButton onClick={() => setSettingsOpen(true)}>
|
||||
<SettingsIcon>Settings</SettingsIcon>
|
||||
<SettingsIcon>
|
||||
{t('cardExtension.settingsButtonTitle')}
|
||||
</SettingsIcon>
|
||||
</IconButton>
|
||||
),
|
||||
}
|
||||
|
||||
@@ -31,3 +31,4 @@ export type {
|
||||
CardConfig,
|
||||
} from './extensions';
|
||||
export * from './overridableComponents';
|
||||
export { homeReactTranslationRef } from './translation';
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const homeReactTranslationRef = createTranslationRef({
|
||||
id: 'home-react',
|
||||
messages: {
|
||||
settingsModal: {
|
||||
title: 'Settings',
|
||||
closeButtonTitle: 'Close',
|
||||
},
|
||||
cardExtension: {
|
||||
settingsButtonTitle: 'Settings',
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -23,6 +23,7 @@ import { ReactNode } from 'react';
|
||||
import { RendererProps as RendererProps_2 } from '@backstage/plugin-home-react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
import { StorageApi } from '@backstage/core-plugin-api';
|
||||
import { TranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { Variant } from '@material-ui/core/styles/createTypography';
|
||||
|
||||
// @public
|
||||
@@ -170,6 +171,38 @@ export const homePlugin: BackstagePlugin<
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const homeTranslationRef: TranslationRef<
|
||||
'home',
|
||||
{
|
||||
readonly 'starredEntities.noStarredEntitiesMessage': 'Click the star beside an entity name to add it to this list!';
|
||||
readonly 'addWidgetDialog.title': 'Add new widget to dashboard';
|
||||
readonly 'customHomepageButtons.clearAll': 'Clear all';
|
||||
readonly 'customHomepageButtons.edit': 'Edit';
|
||||
readonly 'customHomepageButtons.restoreDefaults': 'Restore defaults';
|
||||
readonly 'customHomepageButtons.addWidget': 'Add widget';
|
||||
readonly 'customHomepageButtons.save': 'Save';
|
||||
readonly 'customHomepage.noWidgets': "No widgets added. Start by clicking the 'Add widget' button.";
|
||||
readonly 'widgetSettingsOverlay.cancelButtonTitle': 'Cancel';
|
||||
readonly 'widgetSettingsOverlay.editSettingsTooptip': 'Edit settings';
|
||||
readonly 'widgetSettingsOverlay.deleteWidgetTooltip': 'Delete widget';
|
||||
readonly 'widgetSettingsOverlay.submitButtonTitle': 'Submit';
|
||||
readonly 'starredEntityListItem.removeFavoriteEntityTitle': 'Remove entity from favorites';
|
||||
readonly 'visitList.empty.title': 'There are no visits to show yet.';
|
||||
readonly 'visitList.empty.description': 'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.';
|
||||
readonly 'visitList.few.title': 'The more pages you visit, the more pages will appear here.';
|
||||
readonly 'quickStart.title': 'Onboarding';
|
||||
readonly 'quickStart.description': 'Get started with Backstage';
|
||||
readonly 'quickStart.learnMoreLinkTitle': 'Learn more';
|
||||
readonly 'visitedByType.action.viewMore': 'View more';
|
||||
readonly 'visitedByType.action.viewLess': 'View less';
|
||||
readonly 'featuredDocsCard.empty.title': 'No documents to show';
|
||||
readonly 'featuredDocsCard.empty.description': 'Create your own document. Check out our Getting Started Information';
|
||||
readonly 'featuredDocsCard.empty.learnMoreLinkTitle': 'DOCS';
|
||||
readonly 'featuredDocsCard.learnMoreTitle': 'LEARN MORE';
|
||||
}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const isOperator: (s: string) => s is Operators;
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar';
|
||||
import AddIcon from '@material-ui/icons/Add';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
interface AddWidgetDialogProps {
|
||||
widgets: Widget[];
|
||||
@@ -35,9 +37,10 @@ const getTitle = (widget: Widget) => {
|
||||
|
||||
export const AddWidgetDialog = (props: AddWidgetDialogProps) => {
|
||||
const { widgets, handleAdd } = props;
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
return (
|
||||
<>
|
||||
<DialogTitle>Add new widget to dashboard</DialogTitle>
|
||||
<DialogTitle>{t('addWidgetDialog.title')}</DialogTitle>
|
||||
<DialogContent>
|
||||
<List dense>
|
||||
{widgets.map(widget => {
|
||||
|
||||
@@ -20,6 +20,8 @@ import DeleteIcon from '@material-ui/icons/Delete';
|
||||
import AddIcon from '@material-ui/icons/Add';
|
||||
import EditIcon from '@material-ui/icons/Edit';
|
||||
import CancelIcon from '@material-ui/icons/Cancel';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -55,6 +57,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
restoreDefault,
|
||||
} = props;
|
||||
const styles = useStyles();
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -66,7 +69,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
size="small"
|
||||
startIcon={<EditIcon />}
|
||||
>
|
||||
Edit
|
||||
{t('customHomepageButtons.edit')}
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
@@ -78,7 +81,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
size="small"
|
||||
startIcon={<CancelIcon />}
|
||||
>
|
||||
Restore defaults
|
||||
{t('customHomepageButtons.restoreDefaults')}
|
||||
</Button>
|
||||
)}
|
||||
{numWidgets > 0 && (
|
||||
@@ -90,7 +93,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
size="small"
|
||||
startIcon={<DeleteIcon />}
|
||||
>
|
||||
Clear all
|
||||
{t('customHomepageButtons.clearAll')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
@@ -100,7 +103,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
size="small"
|
||||
startIcon={<AddIcon />}
|
||||
>
|
||||
Add widget
|
||||
{t('customHomepageButtons.addWidget')}
|
||||
</Button>
|
||||
{numWidgets > 0 && (
|
||||
<Button
|
||||
@@ -111,7 +114,7 @@ export const CustomHomepageButtons = (props: CustomHomepageButtonsProps) => {
|
||||
size="small"
|
||||
startIcon={<SaveIcon />}
|
||||
>
|
||||
Save
|
||||
{t('customHomepageButtons.save')}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -50,6 +50,8 @@ import {
|
||||
WidgetSchema,
|
||||
} from './types';
|
||||
import { CardConfig } from '@backstage/plugin-home-react';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
// eslint-disable-next-line new-cap
|
||||
const ResponsiveGrid = WidthProvider(Responsive);
|
||||
@@ -222,6 +224,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
|
||||
const getWidgetNameFromKey = (key: string) => {
|
||||
return key.split('__')[0];
|
||||
};
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
|
||||
const handleAdd = (widget: Widget) => {
|
||||
const widgetId = `${widget.name}__${widgets.length + 1}${Math.random()
|
||||
@@ -340,7 +343,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
|
||||
</Dialog>
|
||||
{!editMode && widgets.length === 0 && (
|
||||
<Typography variant="h5" align="center">
|
||||
No widgets added. Start by clicking the 'Add widget' button.
|
||||
{t('customHomepage.noWidgets')}
|
||||
</Typography>
|
||||
)}
|
||||
<ResponsiveGrid
|
||||
|
||||
@@ -29,6 +29,8 @@ import { Widget } from './types';
|
||||
import { withTheme } from '@rjsf/core';
|
||||
import { Theme as MuiTheme } from '@rjsf/material-ui';
|
||||
import validator from '@rjsf/validator-ajv8';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
const Form = withTheme(MuiTheme);
|
||||
|
||||
@@ -68,6 +70,7 @@ export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
|
||||
const styles = useStyles();
|
||||
|
||||
const onClose = () => setSettingsDialogOpen(false);
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
|
||||
return (
|
||||
<div className={styles.settingsOverlay}>
|
||||
@@ -98,10 +101,10 @@ export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
|
||||
>
|
||||
<DialogActions>
|
||||
<Button color="primary" variant="contained" type="submit">
|
||||
Submit
|
||||
{t('widgetSettingsOverlay.submitButtonTitle')}
|
||||
</Button>
|
||||
<Button color="secondary" onClick={onClose}>
|
||||
Cancel
|
||||
{t('widgetSettingsOverlay.cancelButtonTitle')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Form>
|
||||
@@ -116,7 +119,7 @@ export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
|
||||
>
|
||||
{widget.settingsSchema && (
|
||||
<Grid item className="overlayGridItem">
|
||||
<Tooltip title="Edit settings">
|
||||
<Tooltip title={t('widgetSettingsOverlay.editSettingsTooptip')}>
|
||||
<IconButton
|
||||
color="primary"
|
||||
onClick={() => setSettingsDialogOpen(true)}
|
||||
@@ -128,7 +131,7 @@ export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
|
||||
)}
|
||||
{deletable !== false && (
|
||||
<Grid item className="overlayGridItem">
|
||||
<Tooltip title="Delete widget">
|
||||
<Tooltip title={t('widgetSettingsOverlay.deleteWidgetTooltip')}>
|
||||
<IconButton color="secondary" onClick={() => handleRemove(id)}>
|
||||
<DeleteIcon fontSize="large" />
|
||||
</IconButton>
|
||||
|
||||
@@ -26,6 +26,8 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
||||
import { useRouteRef } from '@backstage/core-plugin-api';
|
||||
import { FavoriteToggle } from '@backstage/core-components';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
type EntityListItemProps = {
|
||||
entity: Entity;
|
||||
@@ -50,6 +52,7 @@ export const StarredEntityListItem = ({
|
||||
}: EntityListItemProps) => {
|
||||
const classes = useStyles();
|
||||
const catalogEntityRoute = useRouteRef(entityRouteRef);
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
|
||||
let secondaryText = '';
|
||||
if (showKind) {
|
||||
@@ -80,7 +83,7 @@ export const StarredEntityListItem = ({
|
||||
>
|
||||
<FavoriteToggle
|
||||
id={`remove-favorite-${entity.metadata.uid}`}
|
||||
title="Remove entity from favorites"
|
||||
title={t('starredEntityListItem.removeFavoriteEntityTitle')}
|
||||
isFavorite
|
||||
onToggle={() => onToggleStarredEntity(entity)}
|
||||
/>
|
||||
|
||||
@@ -14,16 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
export const VisitListEmpty = () => (
|
||||
<>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
There are no visits to show yet.
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Once you start using Backstage, your visits will appear here as a quick
|
||||
link to carry on where you left off.
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
export const VisitListEmpty = () => {
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
return (
|
||||
<>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{t('visitList.empty.title')}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{t('visitList.empty.description')}
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,12 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
export const VisitListFew = () => (
|
||||
<>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
The more pages you visit, the more pages will appear here.
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
export const VisitListFew = () => {
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
return (
|
||||
<>
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{t('visitList.few.title')}
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -33,6 +33,8 @@ import { EntityFilterQuery } from '@backstage/catalog-client';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
/**
|
||||
* Props customizing the <FeaturedDocsCard/> component.
|
||||
@@ -88,7 +90,8 @@ const useStyles = makeStyles(
|
||||
export const Content = (props: FeaturedDocsCardProps): JSX.Element => {
|
||||
const { emptyState, filter, linkDestination, responseLimit, subLinkText } =
|
||||
props;
|
||||
const linkText = subLinkText || 'LEARN MORE';
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
const linkText = subLinkText || t('featuredDocsCard.learnMoreTitle');
|
||||
const styles = useStyles();
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const {
|
||||
@@ -153,14 +156,14 @@ export const Content = (props: FeaturedDocsCardProps): JSX.Element => {
|
||||
emptyState || (
|
||||
<EmptyState
|
||||
missing="data"
|
||||
title="No documents to show"
|
||||
description="Create your own document. Check out our Getting Started Information"
|
||||
title={t('featuredDocsCard.empty.title')}
|
||||
description={t('featuredDocsCard.empty.description')}
|
||||
action={
|
||||
<LinkButton
|
||||
to="https://backstage.io/docs/features/techdocs/getting-started"
|
||||
variant="contained"
|
||||
>
|
||||
DOCS
|
||||
{t('featuredDocsCard.empty.learnMoreLinkTitle')}
|
||||
</LinkButton>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -20,6 +20,8 @@ import Typography from '@material-ui/core/Typography';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import { ContentModal } from '@backstage/plugin-home-react';
|
||||
import { useStyles } from './styles';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
/**
|
||||
* Props customizing the <QuickStartCard/> component.
|
||||
@@ -54,14 +56,15 @@ export type QuickStartCardProps = {
|
||||
*/
|
||||
export const Content = (props: QuickStartCardProps): JSX.Element => {
|
||||
const styles = useStyles();
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
return (
|
||||
<>
|
||||
<ContentModal
|
||||
modalContent={props.image}
|
||||
linkContent={props.modalTitle || 'Onboarding'}
|
||||
linkContent={props.modalTitle || t('quickStart.title')}
|
||||
/>
|
||||
<Typography variant="body1" paragraph>
|
||||
{props.cardDescription || 'Get started with Backstage'}
|
||||
{props.cardDescription || t('quickStart.description')}
|
||||
</Typography>
|
||||
<ContentModal modalContent={props.image} linkContent={props.image} />
|
||||
<Grid
|
||||
@@ -78,7 +81,7 @@ export const Content = (props: QuickStartCardProps): JSX.Element => {
|
||||
variant="h6"
|
||||
className={styles.link}
|
||||
>
|
||||
{props.docsLinkTitle || 'Learn more'}
|
||||
{props.docsLinkTitle || t('quickStart.learnMoreLinkTitle')}
|
||||
</Link>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -29,6 +29,8 @@ import { ReactNode, useState } from 'react';
|
||||
import useAsync from 'react-use/esm/useAsync';
|
||||
import { StarredEntityListItem } from '../../components/StarredEntityListItem/StarredEntityListItem';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
tabs: {
|
||||
@@ -63,6 +65,7 @@ export const Content = ({
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const { starredEntities, toggleStarredEntity } = useStarredEntities();
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
|
||||
// Grab starred entities from catalog to ensure they still exist and also retrieve display titles
|
||||
const entities = useAsync(async () => {
|
||||
@@ -89,7 +92,7 @@ export const Content = ({
|
||||
return (
|
||||
<Typography variant="body1">
|
||||
{noStarredEntitiesMessage ||
|
||||
'Click the star beside an entity name to add it to this list!'}
|
||||
t('starredEntities.noStarredEntitiesMessage')}
|
||||
</Typography>
|
||||
);
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
import { useCallback } from 'react';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { useContext } from './Context';
|
||||
import { useTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
import { homeTranslationRef } from '../../translation';
|
||||
|
||||
export const Actions = () => {
|
||||
const { collapsed, setCollapsed, visits, numVisitsOpen, loading } =
|
||||
@@ -25,7 +27,10 @@ export const Actions = () => {
|
||||
() => setCollapsed(prevCollapsed => !prevCollapsed),
|
||||
[setCollapsed],
|
||||
);
|
||||
const label = collapsed ? 'View More' : 'View Less';
|
||||
const { t } = useTranslationRef(homeTranslationRef);
|
||||
const label = collapsed
|
||||
? t('visitedByType.action.viewMore')
|
||||
: t('visitedByType.action.viewLess');
|
||||
|
||||
if (!loading && visits.length <= numVisitsOpen) return <></>;
|
||||
|
||||
|
||||
@@ -42,3 +42,4 @@ export * from './assets';
|
||||
export * from './homePageComponents';
|
||||
export * from './deprecated';
|
||||
export * from './api';
|
||||
export { homeTranslationRef } from './translation';
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createTranslationRef } from '@backstage/frontend-plugin-api';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const homeTranslationRef = createTranslationRef({
|
||||
id: 'home',
|
||||
messages: {
|
||||
addWidgetDialog: {
|
||||
title: 'Add new widget to dashboard',
|
||||
},
|
||||
customHomepageButtons: {
|
||||
edit: 'Edit',
|
||||
restoreDefaults: 'Restore defaults',
|
||||
clearAll: 'Clear all',
|
||||
addWidget: 'Add widget',
|
||||
save: 'Save',
|
||||
},
|
||||
customHomepage: {
|
||||
noWidgets: "No widgets added. Start by clicking the 'Add widget' button.",
|
||||
},
|
||||
widgetSettingsOverlay: {
|
||||
editSettingsTooptip: 'Edit settings',
|
||||
deleteWidgetTooltip: 'Delete widget',
|
||||
submitButtonTitle: 'Submit',
|
||||
cancelButtonTitle: 'Cancel',
|
||||
},
|
||||
starredEntityListItem: {
|
||||
removeFavoriteEntityTitle: 'Remove entity from favorites',
|
||||
},
|
||||
visitList: {
|
||||
empty: {
|
||||
title: 'There are no visits to show yet.',
|
||||
description:
|
||||
'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.',
|
||||
},
|
||||
few: {
|
||||
title: 'The more pages you visit, the more pages will appear here.',
|
||||
},
|
||||
},
|
||||
quickStart: {
|
||||
title: 'Onboarding',
|
||||
description: 'Get started with Backstage',
|
||||
learnMoreLinkTitle: 'Learn more',
|
||||
},
|
||||
starredEntities: {
|
||||
noStarredEntitiesMessage:
|
||||
'Click the star beside an entity name to add it to this list!',
|
||||
},
|
||||
visitedByType: {
|
||||
action: {
|
||||
viewMore: 'View more',
|
||||
viewLess: 'View less',
|
||||
},
|
||||
},
|
||||
featuredDocsCard: {
|
||||
learnMoreTitle: 'LEARN MORE',
|
||||
empty: {
|
||||
title: 'No documents to show',
|
||||
description:
|
||||
'Create your own document. Check out our Getting Started Information',
|
||||
learnMoreLinkTitle: 'DOCS',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -6727,6 +6727,7 @@ __metadata:
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/core-components": "workspace:^"
|
||||
"@backstage/core-plugin-api": "workspace:^"
|
||||
"@backstage/frontend-plugin-api": "workspace:^"
|
||||
"@material-ui/core": "npm:^4.12.2"
|
||||
"@material-ui/icons": "npm:^4.9.1"
|
||||
"@rjsf/utils": "npm:5.23.2"
|
||||
|
||||
Reference in New Issue
Block a user