From 2ae63cd7a700aa45157cb69cee7af4de19d1c95f Mon Sep 17 00:00:00 2001 From: mario ma Date: Tue, 30 Jul 2024 11:23:25 +0800 Subject: [PATCH 1/5] feat: add i18n for scaffolder Signed-off-by: mario ma --- .changeset/many-years-lie.md | 5 + plugins/scaffolder/src/alpha.tsx | 2 + .../components/ActionsPage/ActionsPage.tsx | 34 ++- .../ListTasksPage/ListTasksPage.tsx | 26 +- .../ListTasksPage/OwnerListPicker.tsx | 18 +- .../components/OngoingTask/ContextMenu.tsx | 21 +- .../components/OngoingTask/OngoingTask.tsx | 21 +- .../TemplateTypePicker.test.tsx | 6 +- .../TemplateTypePicker/TemplateTypePicker.tsx | 5 +- .../EntityNamePicker/EntityNamePicker.tsx | 8 +- .../fields/EntityPicker/EntityPicker.tsx | 8 +- .../EntityTagsPicker/EntityTagsPicker.tsx | 10 +- .../MyGroupsPicker/MyGroupsPicker.test.tsx | 12 +- .../fields/MyGroupsPicker/MyGroupsPicker.tsx | 8 +- .../OwnedEntityPicker/OwnedEntityPicker.tsx | 8 +- .../fields/OwnerPicker/OwnerPicker.tsx | 8 +- .../RepoUrlPicker/AzureRepoPicker.test.tsx | 13 +- .../fields/RepoUrlPicker/AzureRepoPicker.tsx | 65 ++-- .../BitbucketRepoPicker.test.tsx | 34 +-- .../RepoUrlPicker/BitbucketRepoPicker.tsx | 24 +- .../RepoUrlPicker/GerritRepoPicker.test.tsx | 11 +- .../fields/RepoUrlPicker/GerritRepoPicker.tsx | 13 +- .../RepoUrlPicker/GiteaRepoPicker.test.tsx | 7 +- .../fields/RepoUrlPicker/GiteaRepoPicker.tsx | 41 +-- .../RepoUrlPicker/GithubRepoPicker.test.tsx | 13 +- .../fields/RepoUrlPicker/GithubRepoPicker.tsx | 34 ++- .../RepoUrlPicker/GitlabRepoPicker.test.tsx | 13 +- .../fields/RepoUrlPicker/GitlabRepoPicker.tsx | 41 +-- .../RepoUrlPicker/RepoUrlPickerHost.tsx | 7 +- .../RepoUrlPickerRepoName.test.tsx | 11 +- .../RepoUrlPicker/RepoUrlPickerRepoName.tsx | 15 +- .../CustomFieldExplorer.tsx | 19 +- .../DryRunResults/DryRunResults.tsx | 5 +- .../DryRunResults/DryRunResultsList.tsx | 17 +- .../DryRunResults/DryRunResultsView.tsx | 18 +- .../DryRunResults/TaskStatusStepper.tsx | 9 +- .../TemplateEditorBrowser.tsx | 19 +- .../TemplateEditorIntro.tsx | 26 +- .../TemplateEditorPage/TemplateEditorPage.tsx | 7 +- .../TemplateEditorTextArea.tsx | 15 +- .../TemplateFormPreviewer.tsx | 7 +- .../TemplateListPage/TemplateListPage.tsx | 45 +-- .../TemplateWizardPage/TemplateWizardPage.tsx | 9 +- .../TemplateWizardPageContextMenu.tsx | 9 +- plugins/scaffolder/src/translation.ts | 286 ++++++++++++++++++ 45 files changed, 776 insertions(+), 257 deletions(-) create mode 100644 .changeset/many-years-lie.md create mode 100644 plugins/scaffolder/src/translation.ts diff --git a/.changeset/many-years-lie.md b/.changeset/many-years-lie.md new file mode 100644 index 0000000000..8615ddba21 --- /dev/null +++ b/.changeset/many-years-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +add i18n for scaffolder diff --git a/plugins/scaffolder/src/alpha.tsx b/plugins/scaffolder/src/alpha.tsx index 3136626f47..5b7353053e 100644 --- a/plugins/scaffolder/src/alpha.tsx +++ b/plugins/scaffolder/src/alpha.tsx @@ -106,3 +106,5 @@ export default createFrontendPlugin({ }), extensions: [scaffolderApi, scaffolderPage, scaffolderNavItem], }); + +export * from './translation'; \ No newline at end of file diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 7e859e272d..2f9bcba279 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -58,6 +58,8 @@ import { rootRouteRef, scaffolderListTaskRouteRef, } from '../../routes'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; const useStyles = makeStyles(theme => ({ code: { @@ -115,6 +117,7 @@ const ExamplesTable = (props: { examples: ActionExample[] }) => { const ActionPageContent = () => { const api = useApi(scaffolderApiRef); + const { t } = useTranslationRef(scaffolderTranslationRef); const classes = useStyles(); const { loading, value, error } = useAsync(async () => { @@ -132,8 +135,8 @@ const ActionPageContent = () => { ); @@ -141,17 +144,21 @@ const ActionPageContent = () => { const renderTable = (rows?: JSX.Element[]) => { if (!rows || rows.length < 1) { - return No schema defined; + return ( + {t('actionsPage.content.noRowsDescription')} + ); } return ( - Name - Title - Description - Type + {t('actionsPage.content.tableCell.name')} + {t('actionsPage.content.tableCell.title')} + + {t('actionsPage.content.tableCell.description')} + + {t('actionsPage.content.tableCell.type')} {rows} @@ -295,7 +302,7 @@ const ActionPageContent = () => { {action.schema?.input && ( - Input + {t('actionsPage.action.input')} {renderTable( formatRows(`${action.id}.input`, action?.schema?.input), @@ -306,7 +313,7 @@ const ActionPageContent = () => { {action.schema?.output && ( - Output + {t('actionsPage.action.output')} {renderTable( formatRows(`${action.id}.output`, action?.schema?.output), @@ -317,7 +324,7 @@ const ActionPageContent = () => { }> - Examples + {t('actionsPage.action.examples')} @@ -336,6 +343,7 @@ export const ActionsPage = () => { const editorLink = useRouteRef(editRouteRef); const tasksLink = useRouteRef(scaffolderListTaskRouteRef); const createLink = useRouteRef(rootRouteRef); + const { t } = useTranslationRef(scaffolderTranslationRef); const scaffolderPageContextMenuProps = { onEditorClicked: () => navigate(editorLink()), @@ -347,9 +355,9 @@ export const ActionsPage = () => { return (
diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx index d37716a710..7bc34662ef 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx @@ -41,6 +41,8 @@ import { import { actionsRouteRef, editRouteRef, rootRouteRef } from '../../routes'; import { ScaffolderPageContextMenu } from '@backstage/plugin-scaffolder-react/alpha'; import { useNavigate } from 'react-router-dom'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; export interface MyTaskPageProps { initiallySelectedFilter?: 'owned' | 'all'; @@ -48,6 +50,7 @@ export interface MyTaskPageProps { const ListTaskPageContent = (props: MyTaskPageProps) => { const { initiallySelectedFilter = 'owned' } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const scaffolderApi = useApi(scaffolderApiRef); const rootLink = useRouteRef(rootRouteRef); @@ -76,8 +79,8 @@ const ListTaskPageContent = (props: MyTaskPageProps) => { ); @@ -94,17 +97,17 @@ const ListTaskPageContent = (props: MyTaskPageProps) => { data={value?.tasks ?? []} - title="Tasks" + title={t('listTaskPage.content.tableTitle')} columns={[ { - title: 'Task ID', + title: t('listTaskPage.content.tableCell.taskID'), field: 'id', render: row => ( {row.id} ), }, { - title: 'Template', + title: t('listTaskPage.content.tableCell.template'), field: 'spec.templateInfo.entity.metadata.title', render: row => ( { ), }, { - title: 'Created', + title: t('listTaskPage.content.tableCell.created'), field: 'createdAt', render: row => , }, { - title: 'Owner', + title: t('listTaskPage.content.tableCell.owner'), field: 'createdBy', render: row => ( ), }, { - title: 'Status', + title: t('listTaskPage.content.tableCell.status'), field: 'status', render: row => , }, @@ -141,6 +144,7 @@ export const ListTasksPage = (props: MyTaskPageProps) => { const editorLink = useRouteRef(editRouteRef); const actionsLink = useRouteRef(actionsRouteRef); const createLink = useRouteRef(rootRouteRef); + const { t } = useTranslationRef(scaffolderTranslationRef); const scaffolderPageContextMenuProps = { onEditorClicked: () => navigate(editorLink()), @@ -151,9 +155,9 @@ export const ListTasksPage = (props: MyTaskPageProps) => { return (
diff --git a/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx b/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx index d2489303d3..00efed45ba 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx @@ -23,6 +23,11 @@ import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import SettingsIcon from '@material-ui/icons/Settings'; import React, { Fragment } from 'react'; +import { + TranslationFunction, + useTranslationRef, +} from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; import AllIcon from '@material-ui/icons/FontDownload'; @@ -64,19 +69,21 @@ export type ButtonGroup = { }[]; }; -function getFilterGroups(): ButtonGroup[] { +function getFilterGroups( + t: TranslationFunction, +): ButtonGroup[] { return [ { - name: 'Task Owner', + name: t('ownerListPicker.title'), items: [ { id: 'owned', - label: 'Owned', + label: t('ownerListPicker.options.owned'), icon: SettingsIcon, }, { id: 'all', - label: 'All', + label: t('ownerListPicker.options.all'), icon: AllIcon, }, ], @@ -90,8 +97,9 @@ export const OwnerListPicker = (props: { }) => { const { filter, onSelectOwner } = props; const classes = useStyles(); + const { t } = useTranslationRef(scaffolderTranslationRef); - const filterGroups = getFilterGroups(); + const filterGroups = getFilterGroups(t); return ( {filterGroups.map(group => ( diff --git a/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx index f96f83fd2f..e0ab01fc67 100644 --- a/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx +++ b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx @@ -36,6 +36,8 @@ import { taskReadPermission, taskCreatePermission, } from '@backstage/plugin-scaffolder-common/alpha'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; type ContextMenuProps = { cancelEnabled?: boolean; @@ -69,6 +71,7 @@ export const ContextMenu = (props: ContextMenuProps) => { const scaffolderApi = useApi(scaffolderApiRef); const analytics = useAnalytics(); const [anchorEl, setAnchorEl] = useState(); + const { t } = useTranslationRef(scaffolderTranslationRef); const [{ status: cancelStatus }, { execute: cancel }] = useAsync(async () => { if (taskId) { @@ -118,14 +121,24 @@ export const ContextMenu = (props: ContextMenuProps) => { - + onToggleButtonBar?.(!buttonBarVisible)}> { - + { - + diff --git a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx index 459ba682d2..b956e27aca 100644 --- a/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx @@ -42,6 +42,8 @@ import { taskReadPermission, taskCreatePermission, } from '@backstage/plugin-scaffolder-common/alpha'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; const useStyles = makeStyles(theme => ({ contentWrapper: { @@ -85,6 +87,7 @@ export const OngoingTask = (props: { })) ?? [], [taskStream], ); + const { t } = useTranslationRef(scaffolderTranslationRef); const [logsVisible, setLogVisibleState] = useState(false); const [buttonBarVisible, setButtonBarVisibleState] = useState(true); @@ -166,7 +169,7 @@ export const OngoingTask = (props: { const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs; const templateName = - taskStream.task?.spec.templateInfo?.entity?.metadata.name; + taskStream.task?.spec.templateInfo?.entity?.metadata.name || ''; const cancelEnabled = !(taskStream.cancelled || taskStream.completed); @@ -174,14 +177,16 @@ export const OngoingTask = (props: {
- Run of {templateName} + {t('ongoingTask.title')} {templateName} } - subtitle={`Task ${taskId}`} + subtitle={t('ongoingTask.subtitle', { taskId: taskId as string })} > - Cancel + {t('ongoingTask.cancelButtonTitle')} diff --git a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx index aa6630d4aa..4c4b88e471 100644 --- a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx +++ b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx @@ -26,7 +26,7 @@ import { } from '@backstage/plugin-catalog-react'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; import { ApiProvider } from '@backstage/core-app-api'; -import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; +import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { GetEntityFacetsResponse } from '@backstage/catalog-client'; const entities: Entity[] = [ @@ -86,7 +86,7 @@ const apis = TestApiRegistry.from( describe('', () => { it('renders available entity types', async () => { - const rendered = await renderWithEffects( + const rendered = await renderInTestApp( ', () => { }); it('sets the selected type filters', async () => { - const rendered = await renderWithEffects( + const rendered = await renderInTestApp( ; const checkedIcon = ; @@ -41,6 +43,7 @@ export const TemplateTypePicker = () => { const alertApi = useApi(alertApiRef); const { error, loading, availableTypes, selectedTypes, setSelectedTypes } = useEntityTypeFilter(); + const { t } = useTranslationRef(scaffolderTranslationRef); if (loading) return ; @@ -61,7 +64,7 @@ export const TemplateTypePicker = () => { component="label" htmlFor="categories-picker" > - Categories + {t('templateTypePicker.title')} id="categories-picker" diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx index 9f49fc2b94..c219ae0d63 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx @@ -16,6 +16,8 @@ import React from 'react'; import { EntityNamePickerProps } from './schema'; import TextField from '@material-ui/core/TextField'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export { EntityNamePickerSchema } from './schema'; @@ -23,10 +25,14 @@ export { EntityNamePickerSchema } from './schema'; * EntityName Picker */ export const EntityNamePicker = (props: EntityNamePickerProps) => { + const { t } = useTranslationRef(scaffolderTranslationRef); const { onChange, required, - schema: { title = 'Name', description = 'Unique name of the component' }, + schema: { + title = t('fields.entityNamePicker.title'), + description = t('fields.entityNamePicker.description'), + }, rawErrors, formData, uiSchema: { 'ui:autofocus': autoFocus }, diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 9eca3e85c5..b97b776b19 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -44,6 +44,8 @@ import { EntityPickerFilterQuery, } from './schema'; import { VirtualizedListbox } from '../VirtualizedListbox'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export { EntityPickerSchema } from './schema'; @@ -54,9 +56,13 @@ export { EntityPickerSchema } from './schema'; * @public */ export const EntityPicker = (props: EntityPickerProps) => { + const { t } = useTranslationRef(scaffolderTranslationRef); const { onChange, - schema: { title = 'Entity', description = 'An entity from the catalog' }, + schema: { + title = t('fields.entityPicker.title'), + description = t('fields.entityPicker.description'), + }, required, uiSchema, rawErrors, diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx index bf95a08c85..25b5d926a5 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx @@ -24,6 +24,8 @@ import FormControl from '@material-ui/core/FormControl'; import TextField from '@material-ui/core/TextField'; import Autocomplete from '@material-ui/lab/Autocomplete'; import { EntityTagsPickerProps } from './schema'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export { EntityTagsPickerSchema } from './schema'; @@ -43,6 +45,7 @@ export const EntityTagsPicker = (props: EntityTagsPickerProps) => { const kinds = uiSchema['ui:options']?.kinds; const showCounts = uiSchema['ui:options']?.showCounts; const helperText = uiSchema['ui:options']?.helperText; + const { t } = useTranslationRef(scaffolderTranslationRef); const { loading, value: existingTags } = useAsync(async () => { const facet = 'metadata.tags'; @@ -109,13 +112,10 @@ export const EntityTagsPicker = (props: EntityTagsPickerProps) => { renderInput={params => ( setInputValue(e.target.value)} error={inputError} - helperText={ - helperText ?? - "Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters" - } + helperText={helperText ?? t('fields.entityTagsPicker.description')} FormHelperTextProps={{ margin: 'dense', style: { marginLeft: 0 } }} /> )} diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx index 4e54ee99ad..74af578a21 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx @@ -15,10 +15,10 @@ */ import React from 'react'; -import { render, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; import { MyGroupsPicker } from './MyGroupsPicker'; -import { TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { catalogApiRef, entityPresentationApiRef, @@ -115,7 +115,7 @@ describe('', () => { required, } as unknown as FieldProps; - render( + await renderInTestApp( ', () => { required, } as unknown as FieldProps; - const { queryByText, getByRole } = render( + const { queryByText, getByRole } = await renderInTestApp( ', () => { required, } as unknown as FieldProps; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( ', () => { formData: 'group:default/group1', } as unknown as FieldProps; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( { + const { t } = useTranslationRef(scaffolderTranslationRef); const { - schema: { title, description }, + schema: { + title = t('fields.myGroupsPicker.title'), + description = t('fields.myGroupsPicker.description'), + }, required, rawErrors, onChange, diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index 02c437ceb6..06fdf17824 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -23,6 +23,8 @@ import { EntityPicker } from '../EntityPicker/EntityPicker'; import { OwnedEntityPickerProps } from './schema'; import { EntityPickerProps } from '../EntityPicker/schema'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export { OwnedEntityPickerSchema } from './schema'; @@ -33,8 +35,12 @@ export { OwnedEntityPickerSchema } from './schema'; * @public */ export const OwnedEntityPicker = (props: OwnedEntityPickerProps) => { + const { t } = useTranslationRef(scaffolderTranslationRef); const { - schema: { title = 'Entity', description = 'An entity from the catalog' }, + schema: { + title = t('fields.ownedEntityPicker.title'), + description = t('fields.ownedEntityPicker.description'), + }, uiSchema, required, } = props; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx index 5c69e73e12..792685f040 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx @@ -16,6 +16,8 @@ import React from 'react'; import { EntityPicker } from '../EntityPicker/EntityPicker'; import { OwnerPickerProps } from './schema'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export { OwnerPickerSchema } from './schema'; @@ -26,8 +28,12 @@ export { OwnerPickerSchema } from './schema'; * @public */ export const OwnerPicker = (props: OwnerPickerProps) => { + const { t } = useTranslationRef(scaffolderTranslationRef); const { - schema: { title = 'Owner', description = 'The owner of the component' }, + schema: { + title = t('fields.ownerPicker.title'), + description = t('fields.ownerPicker.description'), + }, uiSchema, ...restProps } = props; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.test.tsx index 0380ac6ce8..904fb615eb 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.test.tsx @@ -16,11 +16,12 @@ import React from 'react'; import { AzureRepoPicker } from './AzureRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; describe('AzureRepoPicker', () => { it('renders the two input fields', async () => { - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ); @@ -30,9 +31,9 @@ describe('AzureRepoPicker', () => { }); describe('org field', () => { - it('calls onChange when the organisation changes', () => { + it('calls onChange when the organisation changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ); @@ -45,9 +46,9 @@ describe('AzureRepoPicker', () => { }); describe('project field', () => { - it('calls onChange when the project changes', () => { + it('calls onChange when the project changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx index c7b0f1f887..59e666482a 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx @@ -20,6 +20,8 @@ import FormHelperText from '@material-ui/core/FormHelperText'; import TextField from '@material-ui/core/TextField'; import { BaseRepoUrlPickerProps } from './types'; import { Select, SelectItem } from '@backstage/core-components'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export const AzureRepoPicker = ( props: BaseRepoUrlPickerProps<{ @@ -34,6 +36,7 @@ export const AzureRepoPicker = ( state, onChange, } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const organizationItems: SelectItem[] = allowedOrganizations ? allowedOrganizations.map(i => ({ label: i, value: i })) @@ -53,27 +56,30 @@ export const AzureRepoPicker = ( error={rawErrors?.length > 0 && !organization} > {allowedOrganizations?.length ? ( - + onChange({ organization: String(Array.isArray(s) ? s[0] : s) }) + } + disabled={allowedOrganizations.length === 1} + selected={organization} + items={organizationItems} + /> + + {t('fields.azureRepoPicker.organization.description')} + + ) : ( onChange({ organization: e.target.value })} + helperText={t('fields.azureRepoPicker.organization.description')} value={organization} /> )} - - The Organization that this repo will belong to - 0 && !project} > {allowedProject?.length ? ( - + onChange({ project: String(Array.isArray(s) ? s[0] : s) }) + } + disabled={allowedProject.length === 1} + selected={project} + items={projectItems} + /> + + {t('fields.azureRepoPicker.project.description')} + + ) : ( onChange({ project: e.target.value })} value={project} + helperText={t('fields.azureRepoPicker.project.description')} /> )} - - The Project that this repo will belong to - ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx index 570c5bd664..05d04886e4 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/BitbucketRepoPicker.test.tsx @@ -16,9 +16,9 @@ import React from 'react'; import { BitbucketRepoPicker } from './BitbucketRepoPicker'; -import { render, fireEvent, waitFor } from '@testing-library/react'; +import { fireEvent, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { ScaffolderApi, scaffolderApiRef, @@ -36,7 +36,7 @@ describe('BitbucketRepoPicker', () => { it('renders a select if there is a list of allowed owners', async () => { const allowedOwners = ['owner1', 'owner2']; - const { findByText } = render( + const { findByText } = await renderInTestApp( { expect(await findByText('owner2')).toBeInTheDocument(); }); - it('renders workspace input when host is bitbucket.org', () => { + it('renders workspace input when host is bitbucket.org', async () => { const state = { host: 'bitbucket.org', workspace: 'lolsWorkspace' }; - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { expect(getAllByRole('textbox')[0]).toHaveValue('lolsWorkspace'); }); - it('hides the workspace input when the host is not bitbucket.org', () => { + it('hides the workspace input when the host is not bitbucket.org', async () => { const state = { host: 'mycustom.domain.bitbucket.org', }; - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { }); describe('workspace field', () => { - it('calls onChange when the workspace changes', () => { + it('calls onChange when the workspace changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { }); describe('project field', () => { - it('calls onChange when the project changes', () => { + it('calls onChange when the project changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { }); it('Does not render a select if the list of allowed projects does not exist', async () => { - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { }); it('Does not render a select if the list of allowed projects is empty', async () => { - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { it('Does render a select if there is a list of allowed projects', async () => { const allowedProjects = ['project1', 'project2']; - const { findByText } = render( + const { findByText } = await renderInTestApp( { it('should populate workspaces if host is set and accessToken is provided', async () => { const onChange = jest.fn(); - const { getAllByRole, getByText } = render( + const { getAllByRole, getByText } = await renderInTestApp( { it('should populate projects if host and workspace are set and accessToken is provided', async () => { const onChange = jest.fn(); - const { getAllByRole, getByText } = render( + const { getAllByRole, getByText } = await renderInTestApp( { it('should populate repositories if host, workspace and project are set and accessToken is provided', async () => { const onChange = jest.fn(); - render( + await renderInTestApp( ({ label: i, value: i })) @@ -164,7 +168,7 @@ export const BitbucketRepoPicker = ( {allowedOwners?.length ? ( onChange({ project: String(Array.isArray(s) ? s[0] : s) }) } @@ -215,14 +223,18 @@ export const BitbucketRepoPicker = ( }} options={availableProjects} renderInput={params => ( - + )} freeSolo autoSelect /> )} - The Project that this repo will belong to + {t('fields.bitbucketRepoPicker.project.description')} diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx index f51d00adf2..f00e286418 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.test.tsx @@ -16,13 +16,14 @@ import React from 'react'; import { GerritRepoPicker } from './GerritRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; describe('GerritRepoPicker', () => { describe('owner input field', () => { - it('calls onChange when the owner input changes', () => { + it('calls onChange when the owner input changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { }); describe('parent field', () => { - it('calls onChange when the parent changes', () => { + it('calls onChange when the parent changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( { const { onChange, rawErrors, state } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const { workspace, owner } = state; return ( <> 0 && !workspace}> onChange({ owner: e.target.value })} + helperText={t('fields.gerritRepoPicker.owner.description')} value={owner} /> - The owner of the project (optional) { > onChange({ workspace: e.target.value })} value={workspace} + helperText={t('fields.gerritRepoPicker.parent.description')} /> - - The project parent that the repo will belong to - ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GiteaRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GiteaRepoPicker.test.tsx index e66ca49af1..056d8f0d11 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GiteaRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GiteaRepoPicker.test.tsx @@ -16,13 +16,14 @@ import React from 'react'; import { GiteaRepoPicker } from './GiteaRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; describe('GiteaRepoPicker', () => { describe('owner input field', () => { - it('calls onChange when the owner input changes', () => { + it('calls onChange when the owner input changes', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ) => { const { allowedOwners = [], state, onChange, rawErrors } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const ownerItems: SelectItem[] = allowedOwners ? allowedOwners.map(i => ({ label: i, value: i })) : [{ label: 'Loading...', value: 'loading' }]; @@ -41,32 +44,36 @@ export const GiteaRepoPicker = ( error={rawErrors?.length > 0 && !owner} > {allowedOwners?.length ? ( - + onChange({ + owner: String( + Array.isArray(selected) ? selected[0] : selected, + ), + }) + } + disabled={allowedOwners.length === 1} + selected={owner} + items={ownerItems} + /> + + {t('fields.giteaRepoPicker.owner.description')} + + ) : ( <> onChange({ owner: e.target.value })} + helperText={t('fields.giteaRepoPicker.owner.description')} value={owner} /> )} - - Gitea namespace where this repository will belong to. It can be the - name of organization, group, subgroup, user, or the project. - ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx index 63bc5b8013..3a01c6de7c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GithubRepoPicker.test.tsx @@ -16,13 +16,14 @@ import React from 'react'; import { GithubRepoPicker } from './GithubRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; describe('GithubRepoPicker', () => { describe('owner field', () => { it('renders a select if there is a list of allowed owners', async () => { const allowedOwners = ['owner1', 'owner2']; - const { findByText } = render( + const { findByText } = await renderInTestApp( { it('calls onChange when the owner is changed to a different owner', async () => { const onChange = jest.fn(); const allowedOwners = ['owner1', 'owner2']; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( { expect(onChange).toHaveBeenCalledWith({ owner: 'owner2' }); }); - it('is disabled picked when only one allowed owner', () => { + it('is disabled picked when only one allowed owner', async () => { const onChange = jest.fn(); const allowedOwners = ['owner1']; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( { it('should display free text if no allowed owners are passed', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ) => { const { allowedOwners = [], rawErrors, state, onChange } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const ownerItems: SelectItem[] = allowedOwners ? allowedOwners.map(i => ({ label: i, value: i })) : [{ label: 'Loading...', value: 'loading' }]; @@ -40,27 +43,30 @@ export const GithubRepoPicker = ( error={rawErrors?.length > 0 && !owner} > {allowedOwners?.length ? ( - + onChange({ owner: String(Array.isArray(s) ? s[0] : s) }) + } + disabled={allowedOwners.length === 1} + selected={owner} + items={ownerItems} + /> + + {t('fields.githubRepoPicker.owner.description')} + + ) : ( onChange({ owner: e.target.value })} + helperText={t('fields.githubRepoPicker.owner.description')} value={owner} /> )} - - The organization, user or project that this repo will belong to - ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx index ad5c7f765e..f3d6e2da91 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GitlabRepoPicker.test.tsx @@ -16,13 +16,14 @@ import React from 'react'; import { GitlabRepoPicker } from './GitlabRepoPicker'; -import { render, fireEvent } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; describe('GitlabRepoPicker', () => { describe('owner field', () => { it('renders a select if there is a list of allowed owners', async () => { const allowedOwners = ['owner1', 'owner2']; - const { findByText } = render( + const { findByText } = await renderInTestApp( { it('calls onChange when the owner is changed to a different owner', async () => { const onChange = jest.fn(); const allowedOwners = ['owner1', 'owner2']; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( { expect(onChange).toHaveBeenCalledWith({ owner: 'owner2' }); }); - it('is disabled picked when only one allowed owner', () => { + it('is disabled picked when only one allowed owner', async () => { const onChange = jest.fn(); const allowedOwners = ['owner1']; - const { getByRole } = render( + const { getByRole } = await renderInTestApp( { it('should display free text if no allowed owners are passed', async () => { const onChange = jest.fn(); - const { getAllByRole } = render( + const { getAllByRole } = await renderInTestApp( , ) => { const { allowedOwners = [], state, onChange, rawErrors } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const ownerItems: SelectItem[] = allowedOwners ? allowedOwners.map(i => ({ label: i, value: i })) : [{ label: 'Loading...', value: 'loading' }]; @@ -41,30 +44,34 @@ export const GitlabRepoPicker = ( error={rawErrors?.length > 0 && !owner} > {allowedOwners?.length ? ( - + onChange({ + owner: String( + Array.isArray(selected) ? selected[0] : selected, + ), + }) + } + disabled={allowedOwners.length === 1} + selected={owner} + items={ownerItems} + /> + + {t('fields.gitlabRepoPicker.owner.description')} + + ) : ( onChange({ owner: e.target.value })} + helperText={t('fields.gitlabRepoPicker.owner.description')} value={owner} /> )} - - GitLab namespace where this repository will belong to. It can be the - name of organization, group, subgroup, user, or the project. - ); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx index ed06983f90..86adc5ee20 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx @@ -20,6 +20,8 @@ import FormHelperText from '@material-ui/core/FormHelperText'; import { useApi } from '@backstage/core-plugin-api'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import useAsync from 'react-use/esm/useAsync'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../../translation'; export const RepoUrlPickerHost = (props: { host?: string; @@ -28,6 +30,7 @@ export const RepoUrlPickerHost = (props: { rawErrors: string[]; }) => { const { host, hosts, onChange, rawErrors } = props; + const { t } = useTranslationRef(scaffolderTranslationRef); const scaffolderApi = useApi(scaffolderApiRef); const { value: { integrations } = { integrations: [] }, loading } = useAsync( @@ -73,7 +76,7 @@ export const RepoUrlPickerHost = (props: { onChange(String(Array.isArray(selected) ? selected[0] : selected)) } @@ -69,13 +72,19 @@ export const RepoUrlPickerRepoName = (props: { }} options={availableRepos || []} renderInput={params => ( - + )} freeSolo autoSelect /> )} - The name of the repository + + {t('fields.repoUrlPickerRepoName.repository.description')} + ); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx index bddf891ec6..041ef9483f 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx @@ -33,6 +33,8 @@ import { Form } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; import validator from '@rjsf/validator-ajv8'; import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; const useStyles = makeStyles(theme => ({ root: { @@ -68,6 +70,7 @@ export const CustomFieldExplorer = ({ onClose?: () => void; }) => { const classes = useStyles(); + const { t } = useTranslationRef(scaffolderTranslationRef); const fieldOptions = customFieldExtensions.filter(field => !!field.schema); const [selectedField, setSelectedField] = useState(fieldOptions[0]); const [fieldFormState, setFieldFormState] = useState({}); @@ -120,11 +123,11 @@ export const CustomFieldExplorer = ({
- Choose Custom Field Extension + {t('templateEditorPage.customFieldExplorer.selectFieldLabel')} handleSelectChange(e.target.value)} > diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index b1508e43fc..400bc9d192 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -52,6 +52,11 @@ import { } from '../../routes'; import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; +import { + TranslationFunction, + useTranslationRef, +} from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; /** * @alpha @@ -74,17 +79,13 @@ export type TemplateListPageProps = { }; }; -const defaultGroup: TemplateGroupFilter = { - title: 'Templates', - filter: () => true, -}; - const createGroupsWithOther = ( groups: TemplateGroupFilter[], + t: TranslationFunction, ): TemplateGroupFilter[] => [ ...groups, { - title: 'Other Templates', + title: t('templateListPage.templateGroups.otherTitle'), filter: e => ![...groups].some(({ filter }) => filter(e)), }, ]; @@ -107,10 +108,16 @@ export const TemplateListPage = (props: TemplateListPageProps) => { const viewTechDocsLink = useRouteRef(viewTechDocRouteRef); const templateRoute = useRouteRef(selectedTemplateRouteRef); const app = useApp(); + const { t } = useTranslationRef(scaffolderTranslationRef); const groups = givenGroups.length - ? createGroupsWithOther(givenGroups) - : [defaultGroup]; + ? createGroupsWithOther(givenGroups, t) + : [ + { + title: t('templateListPage.templateGroups.defaultTitle'), + filter: () => true, + }, + ]; const scaffolderPageContextMenuProps = { onEditorClicked: @@ -137,13 +144,15 @@ export const TemplateListPage = (props: TemplateListPageProps) => { ? [ { icon: app.getSystemIcon('docs') ?? DocsIcon, - text: 'View TechDocs', + text: t( + 'templateListPage.additionalLinksForEntity.viewTechDocsTitle', + ), url: viewTechDocsLink({ kind, namespace, name }), }, ] : []; }, - [app, viewTechDocsLink], + [app, viewTechDocsLink, t], ); const onTemplateSelected = useCallback( @@ -159,23 +168,23 @@ export const TemplateListPage = (props: TemplateListPageProps) => {
- + - Create new software components using standard templates. Different - templates create different kinds of components (services, - websites, documentation, ...). + {t('templateListPage.contentHeader.supportButtonTitle')} diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index aef6ca6bb1..0524b99f8f 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -45,6 +45,8 @@ import { scaffolderTaskRouteRef, selectedTemplateRouteRef, } from '../../routes'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; import { TemplateWizardPageContextMenu } from './TemplateWizardPageContextMenu'; @@ -75,6 +77,7 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { const { templateName, namespace } = useRouteRefParams( selectedTemplateRouteRef, ); + const { t } = useTranslationRef(scaffolderTranslationRef); const templateRef = stringifyEntityRef({ kind: 'Template', @@ -103,9 +106,9 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => {
diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPageContextMenu.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPageContextMenu.tsx index c4927d5d14..50e406112a 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPageContextMenu.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPageContextMenu.tsx @@ -24,6 +24,8 @@ import { makeStyles } from '@material-ui/core/styles'; import Edit from '@material-ui/icons/Edit'; import MoreVert from '@material-ui/icons/MoreVert'; import React, { useState } from 'react'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { scaffolderTranslationRef } from '../../translation'; const useStyles = makeStyles(theme => ({ button: { @@ -41,6 +43,7 @@ export function TemplateWizardPageContextMenu( const { editUrl } = props; const classes = useStyles(); const [anchorEl, setAnchorEl] = useState(); + const { t } = useTranslationRef(scaffolderTranslationRef); if (!editUrl) { return null; @@ -83,7 +86,11 @@ export function TemplateWizardPageContextMenu( - + diff --git a/plugins/scaffolder/src/translation.ts b/plugins/scaffolder/src/translation.ts new file mode 100644 index 0000000000..eb6e4d005a --- /dev/null +++ b/plugins/scaffolder/src/translation.ts @@ -0,0 +1,286 @@ +/* + * Copyright 2024 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/core-plugin-api/alpha'; + +/** @alpha */ +export const scaffolderTranslationRef = createTranslationRef({ + id: 'scaffolder', + messages: { + actionsPage: { + title: 'Installed actions', + pageTitle: 'Create a New Component', + subtitle: 'This is the collection of all installed actions', + content: { + emptyState: { + title: 'No information to display', + description: + 'There are no actions installed or there was an issue communicating with backend.', + }, + tableCell: { + name: 'Name', + title: 'Title', + description: 'Description', + type: 'Type', + }, + noRowsDescription: 'No schema defined', + }, + action: { + input: 'Input', + output: 'Output', + examples: 'Examples', + }, + }, + fields: { + entityNamePicker: { + title: 'Name', + description: 'Unique name of the component', + }, + entityPicker: { + title: 'Entity', + description: 'An entity from the catalog', + }, + entityTagsPicker: { + title: 'Tags', + description: + "Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters", + }, + myGroupsPicker: { + title: 'Entity', + description: 'An entity from the catalog', + }, + ownedEntityPicker: { + title: 'Entity', + description: 'An entity from the catalog', + }, + ownerPicker: { + title: 'Owner', + description: 'The owner of the component', + }, + azureRepoPicker: { + organization: { + title: 'Organization', + description: 'The Organization that this repo will belong to', + }, + project: { + title: 'Project', + description: 'The Project that this repo will belong to', + }, + }, + bitbucketRepoPicker: { + workspaces: { + title: 'Allowed Workspaces', + inputTitle: 'Workspaces', + description: 'The Workspace that this repo will belong to', + }, + project: { + title: 'Allowed Projects', + inputTitle: 'Projects', + description: 'The Project that this repo will belong to', + }, + }, + gerritRepoPicker: { + owner: { + title: 'Owner', + description: 'The owner of the project (optional)', + }, + parent: { + title: 'Parent', + description: 'The project parent that the repo will belong to', + }, + }, + giteaRepoPicker: { + owner: { + title: 'Owner Available', + inputTitle: 'Owner', + description: + 'Gitea namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.', + }, + }, + githubRepoPicker: { + owner: { + title: 'Owner Available', + inputTitle: 'Owner', + description: + 'The organization, user or project that this repo will belong to', + }, + }, + gitlabRepoPicker: { + owner: { + title: 'Owner Available', + inputTitle: 'Owner', + description: + 'GitLab namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.', + }, + }, + repoUrlPickerHost: { + host: { + title: 'Host', + description: 'The host where the repository will be created', + }, + }, + repoUrlPickerRepoName: { + repository: { + title: 'Repositories Available', + inputTitle: 'Repository', + description: 'The name of the repository', + }, + }, + }, + listTaskPage: { + title: 'List template tasks', + pageTitle: 'Templates Tasks', + subtitle: 'All tasks that have been started', + content: { + emptyState: { + title: 'No information to display', + description: + 'There are no tasks or there was an issue communicating with backend.', + }, + tableTitle: 'Tasks', + tableCell: { + taskID: 'Task ID', + template: 'Template', + created: 'Created', + owner: 'Owner', + status: 'Status', + }, + }, + }, + ownerListPicker: { + title: 'Task Owner', + options: { + owned: 'Owned', + all: 'All', + }, + }, + ongoingTask: { + title: 'Run of', + pageTitle: { + hasTemplateName: 'Run of {{templateName}}', + noTemplateName: 'Scaffolder Run', + }, + subtitle: 'Task {{taskId}}', + cancelButtonTitle: 'Cancel', + startOverButtonTitle: 'Start Over', + hideLogsButtonTitle: 'Hide Logs', + showLogsButtonTitle: 'Show Logs', + contextMenu: { + hideLogs: 'Hide Logs', + showLogs: 'Show Logs', + hideButtonBar: 'Hide Button Bar', + showButtonBar: 'Show Button Bar', + startOver: 'Start Over', + cancel: 'Cancel', + }, + }, + templateTypePicker: { + title: 'Categories', + }, + templateEditorPage: { + title: 'Template Editor', + subTitle: 'Edit, preview, and try out templates and template forms', + dryRunResults: { + title: 'Dry-run results', + }, + dryRunResultsList: { + title: 'Result {{resultId}}', + downloadButtonTitle: 'Download as .zip', + deleteButtonTitle: 'Delete result', + }, + dryRunResultsView: { + tab: { + files: 'Files', + log: 'Log', + output: 'Output', + }, + }, + taskStatusStepper: { + skippedStepTitle: 'Skipped', + }, + customFieldExplorer: { + selectFieldLabel: 'Choose Custom Field Extension', + fieldForm: { + title: 'Field Options', + applyButtonTitle: 'Apply', + }, + preview: { + title: 'Example Template Spec', + }, + }, + templateEditorBrowser: { + closeConfirmMessage: 'Are you sure? Unsaved changes will be lost', + saveIconTooltip: 'Save all files', + reloadIconTooltip: 'Reload directory', + closeIconTooltip: 'Close directory', + }, + templateEditorIntro: { + title: 'Get started by choosing one of the options below', + loadLocal: { + title: 'Load Template Directory', + description: + 'Load a local template directory, allowing you to both edit and try executing your own template.', + unSupportsLoadTooltip: + 'Only supported in some Chromium-based browsers', + }, + formEditor: { + title: 'Edit Template Form', + description: + 'Preview and edit a template form, either using a sample template or by loading a template from the catalog.', + }, + fieldExplorer: { + title: 'Custom Field Explorer', + description: + 'View and play around with available installed custom field extensions.', + }, + }, + templateEditorTextArea: { + saveIconTooltip: 'Save file', + refreshIconTooltip: 'Reload file', + }, + templateFormPreviewer: { + title: 'Load Existing Template', + }, + }, + templateListPage: { + title: 'Create a new component', + subtitle: + 'Create new software components using standard templates in your organization', + pageTitle: 'Create a new component', + templateGroups: { + defaultTitle: 'Templates', + otherTitle: 'Other Templates', + }, + contentHeader: { + title: 'Available Templates', + registerExistingButtonTitle: 'Register Existing Component', + supportButtonTitle: + 'Create new software components using standard templates. Different templates create different kinds of components (services, websites, documentation, ...).', + }, + additionalLinksForEntity: { + viewTechDocsTitle: 'View TechDocs', + }, + }, + templateWizardPage: { + title: 'Create a new component', + subtitle: + 'Create new software components using standard templates in your organization', + pageTitle: 'Create a new component', + pageContextMenu: { + editConfigurationTitle: 'Edit Configuration', + }, + }, + }, +}); From adc4890e7f7e390f7028e2feec1d9909e723eab5 Mon Sep 17 00:00:00 2001 From: mario ma Date: Wed, 14 Aug 2024 14:37:19 +0800 Subject: [PATCH 2/5] fix: add api report alpha Signed-off-by: mario ma --- plugins/scaffolder/api-report-alpha.md | 132 +++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/plugins/scaffolder/api-report-alpha.md b/plugins/scaffolder/api-report-alpha.md index 508fa17fb2..2316f9c80c 100644 --- a/plugins/scaffolder/api-report-alpha.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -21,6 +21,7 @@ import { RouteRef } from '@backstage/frontend-plugin-api'; import { SubRouteRef } from '@backstage/frontend-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; +import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) const _default: BackstagePlugin< @@ -110,6 +111,137 @@ export type FormProps = Pick< 'transformErrors' | 'noHtml5Validate' >; +// @alpha (undocumented) +export const scaffolderTranslationRef: TranslationRef< + 'scaffolder', + { + readonly 'fields.entityNamePicker.title': 'Name'; + readonly 'fields.entityNamePicker.description': 'Unique name of the component'; + readonly 'fields.entityPicker.title': 'Entity'; + readonly 'fields.entityPicker.description': 'An entity from the catalog'; + readonly 'fields.entityTagsPicker.title': 'Tags'; + readonly 'fields.entityTagsPicker.description': "Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters"; + readonly 'fields.myGroupsPicker.title': 'Entity'; + readonly 'fields.myGroupsPicker.description': 'An entity from the catalog'; + readonly 'fields.ownedEntityPicker.title': 'Entity'; + readonly 'fields.ownedEntityPicker.description': 'An entity from the catalog'; + readonly 'fields.ownerPicker.title': 'Owner'; + readonly 'fields.ownerPicker.description': 'The owner of the component'; + readonly 'fields.azureRepoPicker.organization.title': 'Organization'; + readonly 'fields.azureRepoPicker.organization.description': 'The Organization that this repo will belong to'; + readonly 'fields.azureRepoPicker.project.title': 'Project'; + readonly 'fields.azureRepoPicker.project.description': 'The Project that this repo will belong to'; + readonly 'fields.bitbucketRepoPicker.project.title': 'Allowed Projects'; + readonly 'fields.bitbucketRepoPicker.project.description': 'The Project that this repo will belong to'; + readonly 'fields.bitbucketRepoPicker.project.inputTitle': 'Projects'; + readonly 'fields.bitbucketRepoPicker.workspaces.title': 'Allowed Workspaces'; + readonly 'fields.bitbucketRepoPicker.workspaces.description': 'The Workspace that this repo will belong to'; + readonly 'fields.bitbucketRepoPicker.workspaces.inputTitle': 'Workspaces'; + readonly 'fields.gerritRepoPicker.parent.title': 'Parent'; + readonly 'fields.gerritRepoPicker.parent.description': 'The project parent that the repo will belong to'; + readonly 'fields.gerritRepoPicker.owner.title': 'Owner'; + readonly 'fields.gerritRepoPicker.owner.description': 'The owner of the project (optional)'; + readonly 'fields.giteaRepoPicker.owner.title': 'Owner Available'; + readonly 'fields.giteaRepoPicker.owner.description': 'Gitea namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.'; + readonly 'fields.giteaRepoPicker.owner.inputTitle': 'Owner'; + readonly 'fields.githubRepoPicker.owner.title': 'Owner Available'; + readonly 'fields.githubRepoPicker.owner.description': 'The organization, user or project that this repo will belong to'; + readonly 'fields.githubRepoPicker.owner.inputTitle': 'Owner'; + readonly 'fields.gitlabRepoPicker.owner.title': 'Owner Available'; + readonly 'fields.gitlabRepoPicker.owner.description': 'GitLab namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.'; + readonly 'fields.gitlabRepoPicker.owner.inputTitle': 'Owner'; + readonly 'fields.repoUrlPickerHost.host.title': 'Host'; + readonly 'fields.repoUrlPickerHost.host.description': 'The host where the repository will be created'; + readonly 'fields.repoUrlPickerRepoName.repository.title': 'Repositories Available'; + readonly 'fields.repoUrlPickerRepoName.repository.description': 'The name of the repository'; + readonly 'fields.repoUrlPickerRepoName.repository.inputTitle': 'Repository'; + readonly 'actionsPage.content.emptyState.title': 'No information to display'; + readonly 'actionsPage.content.emptyState.description': 'There are no actions installed or there was an issue communicating with backend.'; + readonly 'actionsPage.content.tableCell.type': 'Type'; + readonly 'actionsPage.content.tableCell.name': 'Name'; + readonly 'actionsPage.content.tableCell.title': 'Title'; + readonly 'actionsPage.content.tableCell.description': 'Description'; + readonly 'actionsPage.content.noRowsDescription': 'No schema defined'; + readonly 'actionsPage.title': 'Installed actions'; + readonly 'actionsPage.action.input': 'Input'; + readonly 'actionsPage.action.output': 'Output'; + readonly 'actionsPage.action.examples': 'Examples'; + readonly 'actionsPage.subtitle': 'This is the collection of all installed actions'; + readonly 'actionsPage.pageTitle': 'Create a New Component'; + readonly 'listTaskPage.content.emptyState.title': 'No information to display'; + readonly 'listTaskPage.content.emptyState.description': 'There are no tasks or there was an issue communicating with backend.'; + readonly 'listTaskPage.content.tableCell.template': 'Template'; + readonly 'listTaskPage.content.tableCell.status': 'Status'; + readonly 'listTaskPage.content.tableCell.owner': 'Owner'; + readonly 'listTaskPage.content.tableCell.created': 'Created'; + readonly 'listTaskPage.content.tableCell.taskID': 'Task ID'; + readonly 'listTaskPage.content.tableTitle': 'Tasks'; + readonly 'listTaskPage.title': 'List template tasks'; + readonly 'listTaskPage.subtitle': 'All tasks that have been started'; + readonly 'listTaskPage.pageTitle': 'Templates Tasks'; + readonly 'ownerListPicker.title': 'Task Owner'; + readonly 'ownerListPicker.options.all': 'All'; + readonly 'ownerListPicker.options.owned': 'Owned'; + readonly 'ongoingTask.title': 'Run of'; + readonly 'ongoingTask.contextMenu.cancel': 'Cancel'; + readonly 'ongoingTask.contextMenu.startOver': 'Start Over'; + readonly 'ongoingTask.contextMenu.hideLogs': 'Hide Logs'; + readonly 'ongoingTask.contextMenu.showLogs': 'Show Logs'; + readonly 'ongoingTask.contextMenu.hideButtonBar': 'Hide Button Bar'; + readonly 'ongoingTask.contextMenu.showButtonBar': 'Show Button Bar'; + readonly 'ongoingTask.subtitle': 'Task {{taskId}}'; + readonly 'ongoingTask.pageTitle.hasTemplateName': 'Run of {{templateName}}'; + readonly 'ongoingTask.pageTitle.noTemplateName': 'Scaffolder Run'; + readonly 'ongoingTask.cancelButtonTitle': 'Cancel'; + readonly 'ongoingTask.startOverButtonTitle': 'Start Over'; + readonly 'ongoingTask.hideLogsButtonTitle': 'Hide Logs'; + readonly 'ongoingTask.showLogsButtonTitle': 'Show Logs'; + readonly 'templateTypePicker.title': 'Categories'; + readonly 'templateEditorPage.title': 'Template Editor'; + readonly 'templateEditorPage.subTitle': 'Edit, preview, and try out templates and template forms'; + readonly 'templateEditorPage.dryRunResults.title': 'Dry-run results'; + readonly 'templateEditorPage.dryRunResultsList.title': 'Result {{resultId}}'; + readonly 'templateEditorPage.dryRunResultsList.deleteButtonTitle': 'Delete result'; + readonly 'templateEditorPage.dryRunResultsList.downloadButtonTitle': 'Download as .zip'; + readonly 'templateEditorPage.dryRunResultsView.tab.output': 'Output'; + readonly 'templateEditorPage.dryRunResultsView.tab.log': 'Log'; + readonly 'templateEditorPage.dryRunResultsView.tab.files': 'Files'; + readonly 'templateEditorPage.taskStatusStepper.skippedStepTitle': 'Skipped'; + readonly 'templateEditorPage.customFieldExplorer.selectFieldLabel': 'Choose Custom Field Extension'; + readonly 'templateEditorPage.customFieldExplorer.fieldForm.title': 'Field Options'; + readonly 'templateEditorPage.customFieldExplorer.fieldForm.applyButtonTitle': 'Apply'; + readonly 'templateEditorPage.customFieldExplorer.preview.title': 'Example Template Spec'; + readonly 'templateEditorPage.templateEditorBrowser.closeConfirmMessage': 'Are you sure? Unsaved changes will be lost'; + readonly 'templateEditorPage.templateEditorBrowser.saveIconTooltip': 'Save all files'; + readonly 'templateEditorPage.templateEditorBrowser.reloadIconTooltip': 'Reload directory'; + readonly 'templateEditorPage.templateEditorBrowser.closeIconTooltip': 'Close directory'; + readonly 'templateEditorPage.templateEditorIntro.title': 'Get started by choosing one of the options below'; + readonly 'templateEditorPage.templateEditorIntro.loadLocal.title': 'Load Template Directory'; + readonly 'templateEditorPage.templateEditorIntro.loadLocal.description': 'Load a local template directory, allowing you to both edit and try executing your own template.'; + readonly 'templateEditorPage.templateEditorIntro.loadLocal.unSupportsLoadTooltip': 'Only supported in some Chromium-based browsers'; + readonly 'templateEditorPage.templateEditorIntro.formEditor.title': 'Edit Template Form'; + readonly 'templateEditorPage.templateEditorIntro.formEditor.description': 'Preview and edit a template form, either using a sample template or by loading a template from the catalog.'; + readonly 'templateEditorPage.templateEditorIntro.fieldExplorer.title': 'Custom Field Explorer'; + readonly 'templateEditorPage.templateEditorIntro.fieldExplorer.description': 'View and play around with available installed custom field extensions.'; + readonly 'templateEditorPage.templateEditorTextArea.saveIconTooltip': 'Save file'; + readonly 'templateEditorPage.templateEditorTextArea.refreshIconTooltip': 'Reload file'; + readonly 'templateEditorPage.templateFormPreviewer.title': 'Load Existing Template'; + readonly 'templateListPage.title': 'Create a new component'; + readonly 'templateListPage.subtitle': 'Create new software components using standard templates in your organization'; + readonly 'templateListPage.pageTitle': 'Create a new component'; + readonly 'templateListPage.templateGroups.defaultTitle': 'Templates'; + readonly 'templateListPage.templateGroups.otherTitle': 'Other Templates'; + readonly 'templateListPage.contentHeader.title': 'Available Templates'; + readonly 'templateListPage.contentHeader.registerExistingButtonTitle': 'Register Existing Component'; + readonly 'templateListPage.contentHeader.supportButtonTitle': 'Create new software components using standard templates. Different templates create different kinds of components (services, websites, documentation, ...).'; + readonly 'templateListPage.additionalLinksForEntity.viewTechDocsTitle': 'View TechDocs'; + readonly 'templateWizardPage.title': 'Create a new component'; + readonly 'templateWizardPage.subtitle': 'Create new software components using standard templates in your organization'; + readonly 'templateWizardPage.pageTitle': 'Create a new component'; + readonly 'templateWizardPage.pageContextMenu.editConfigurationTitle': 'Edit Configuration'; + } +>; + // @alpha (undocumented) export type TemplateListPageProps = { TemplateCardComponent?: React_2.ComponentType<{ From fd775fc4a1b6f0909e7d9a8ee8f5bc5906f47a1d Mon Sep 17 00:00:00 2001 From: mario ma Date: Thu, 15 Aug 2024 14:39:54 +0800 Subject: [PATCH 3/5] fix: change some key Signed-off-by: mario ma --- plugins/scaffolder/api-report-alpha.md | 4 ++-- .../src/next/TemplateEditorPage/TemplateEditorIntro.tsx | 2 +- .../src/next/TemplateEditorPage/TemplateEditorPage.tsx | 2 +- plugins/scaffolder/src/translation.ts | 5 ++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder/api-report-alpha.md b/plugins/scaffolder/api-report-alpha.md index 2316f9c80c..f0a68919a4 100644 --- a/plugins/scaffolder/api-report-alpha.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -198,7 +198,7 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'ongoingTask.showLogsButtonTitle': 'Show Logs'; readonly 'templateTypePicker.title': 'Categories'; readonly 'templateEditorPage.title': 'Template Editor'; - readonly 'templateEditorPage.subTitle': 'Edit, preview, and try out templates and template forms'; + readonly 'templateEditorPage.subtitle': 'Edit, preview, and try out templates and template forms'; readonly 'templateEditorPage.dryRunResults.title': 'Dry-run results'; readonly 'templateEditorPage.dryRunResultsList.title': 'Result {{resultId}}'; readonly 'templateEditorPage.dryRunResultsList.deleteButtonTitle': 'Delete result'; @@ -218,7 +218,7 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'templateEditorPage.templateEditorIntro.title': 'Get started by choosing one of the options below'; readonly 'templateEditorPage.templateEditorIntro.loadLocal.title': 'Load Template Directory'; readonly 'templateEditorPage.templateEditorIntro.loadLocal.description': 'Load a local template directory, allowing you to both edit and try executing your own template.'; - readonly 'templateEditorPage.templateEditorIntro.loadLocal.unSupportsLoadTooltip': 'Only supported in some Chromium-based browsers'; + readonly 'templateEditorPage.templateEditorIntro.loadLocal.unsupportedTooltip': 'Only supported in some Chromium-based browsers'; readonly 'templateEditorPage.templateEditorIntro.formEditor.title': 'Edit Template Form'; readonly 'templateEditorPage.templateEditorIntro.formEditor.description': 'Preview and edit a template form, either using a sample template or by loading a template from the catalog.'; readonly 'templateEditorPage.templateEditorIntro.fieldExplorer.title': 'Custom Field Explorer'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx index 2318c90659..d785708a51 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx @@ -83,7 +83,7 @@ export function TemplateEditorIntro(props: EditorIntroProps) { diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 924fe6964e..6e7c921e91 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -121,7 +121,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) {
diff --git a/plugins/scaffolder/src/translation.ts b/plugins/scaffolder/src/translation.ts index eb6e4d005a..bf584bb7ad 100644 --- a/plugins/scaffolder/src/translation.ts +++ b/plugins/scaffolder/src/translation.ts @@ -191,7 +191,7 @@ export const scaffolderTranslationRef = createTranslationRef({ }, templateEditorPage: { title: 'Template Editor', - subTitle: 'Edit, preview, and try out templates and template forms', + subtitle: 'Edit, preview, and try out templates and template forms', dryRunResults: { title: 'Dry-run results', }, @@ -232,8 +232,7 @@ export const scaffolderTranslationRef = createTranslationRef({ title: 'Load Template Directory', description: 'Load a local template directory, allowing you to both edit and try executing your own template.', - unSupportsLoadTooltip: - 'Only supported in some Chromium-based browsers', + unsupportedTooltip: 'Only supported in some Chromium-based browsers', }, formEditor: { title: 'Edit Template Form', From c7a3611cf3f91a33a428943cbc6da08aa607fbfc Mon Sep 17 00:00:00 2001 From: mario ma Date: Thu, 15 Aug 2024 15:00:23 +0800 Subject: [PATCH 4/5] fix: alpha.tsx prettier Signed-off-by: mario ma --- plugins/scaffolder/src/alpha.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder/src/alpha.tsx b/plugins/scaffolder/src/alpha.tsx index 5b7353053e..302dddb800 100644 --- a/plugins/scaffolder/src/alpha.tsx +++ b/plugins/scaffolder/src/alpha.tsx @@ -51,6 +51,8 @@ export { type TemplateWizardPageProps, } from './next'; +export { scaffolderTranslationRef } from './translation'; + const scaffolderApi = ApiBlueprint.make({ params: { factory: createApiFactory({ @@ -106,5 +108,3 @@ export default createFrontendPlugin({ }), extensions: [scaffolderApi, scaffolderPage, scaffolderNavItem], }); - -export * from './translation'; \ No newline at end of file From 52408cbbdfbfc2217567a9ffeb180e5ae9b9439b Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 20 Aug 2024 09:52:31 +0200 Subject: [PATCH 5/5] chore: updating some of the repo picker Signed-off-by: blam --- plugins/scaffolder/api-report-alpha.md | 10 +++++----- .../fields/RepoUrlPicker/GerritRepoPicker.tsx | 1 - .../fields/RepoUrlPicker/RepoUrlPickerHost.tsx | 4 ++-- .../fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx | 6 +++--- plugins/scaffolder/src/translation.ts | 4 +--- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/plugins/scaffolder/api-report-alpha.md b/plugins/scaffolder/api-report-alpha.md index f0a68919a4..007b106665 100644 --- a/plugins/scaffolder/api-report-alpha.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -150,11 +150,11 @@ export const scaffolderTranslationRef: TranslationRef< readonly 'fields.gitlabRepoPicker.owner.title': 'Owner Available'; readonly 'fields.gitlabRepoPicker.owner.description': 'GitLab namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.'; readonly 'fields.gitlabRepoPicker.owner.inputTitle': 'Owner'; - readonly 'fields.repoUrlPickerHost.host.title': 'Host'; - readonly 'fields.repoUrlPickerHost.host.description': 'The host where the repository will be created'; - readonly 'fields.repoUrlPickerRepoName.repository.title': 'Repositories Available'; - readonly 'fields.repoUrlPickerRepoName.repository.description': 'The name of the repository'; - readonly 'fields.repoUrlPickerRepoName.repository.inputTitle': 'Repository'; + readonly 'fields.repoUrlPicker.host.title': 'Host'; + readonly 'fields.repoUrlPicker.host.description': 'The host where the repository will be created'; + readonly 'fields.repoUrlPicker.repository.title': 'Repositories Available'; + readonly 'fields.repoUrlPicker.repository.description': 'The name of the repository'; + readonly 'fields.repoUrlPicker.repository.inputTitle': 'Repository'; readonly 'actionsPage.content.emptyState.title': 'No information to display'; readonly 'actionsPage.content.emptyState.description': 'There are no actions installed or there was an issue communicating with backend.'; readonly 'actionsPage.content.tableCell.type': 'Type'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx index 9a81fd3c48..bcc665976f 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/GerritRepoPicker.tsx @@ -15,7 +15,6 @@ */ import React from 'react'; import FormControl from '@material-ui/core/FormControl'; -import FormHelperText from '@material-ui/core/FormHelperText'; import TextField from '@material-ui/core/TextField'; import { BaseRepoUrlPickerProps } from './types'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx index 86adc5ee20..90f8eaf449 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx @@ -76,7 +76,7 @@ export const RepoUrlPickerHost = (props: { onChange(String(Array.isArray(selected) ? selected[0] : selected)) } @@ -74,7 +74,7 @@ export const RepoUrlPickerRepoName = (props: { renderInput={params => ( )} @@ -83,7 +83,7 @@ export const RepoUrlPickerRepoName = (props: { /> )} - {t('fields.repoUrlPickerRepoName.repository.description')} + {t('fields.repoUrlPicker.repository.description')} diff --git a/plugins/scaffolder/src/translation.ts b/plugins/scaffolder/src/translation.ts index bf584bb7ad..d97c3f6f05 100644 --- a/plugins/scaffolder/src/translation.ts +++ b/plugins/scaffolder/src/translation.ts @@ -125,13 +125,11 @@ export const scaffolderTranslationRef = createTranslationRef({ 'GitLab namespace where this repository will belong to. It can be the name of organization, group, subgroup, user, or the project.', }, }, - repoUrlPickerHost: { + repoUrlPicker: { host: { title: 'Host', description: 'The host where the repository will be created', }, - }, - repoUrlPickerRepoName: { repository: { title: 'Repositories Available', inputTitle: 'Repository',