Skip to content

Commit f0a427c

Browse files
authored
feat(orchestrator): add i18n (#1483)
Signed-off-by: Marek Libra <marek.libra@gmail.com>
1 parent 3e4b15b commit f0a427c

66 files changed

Lines changed: 1481 additions & 248 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-orchestrator-form-react': patch
3+
'@red-hat-developer-hub/backstage-plugin-orchestrator-backend': patch
4+
'@red-hat-developer-hub/backstage-plugin-orchestrator-common': patch
5+
'@red-hat-developer-hub/backstage-plugin-orchestrator': patch
6+
---
7+
8+
Added internationalization to the frontend plugins.

workspaces/orchestrator/packages/app/src/App.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import { apis } from './apis';
5858
import { entityPage } from './components/catalog/EntityPage';
5959
import { Root } from './components/Root';
6060
import { searchPage } from './components/search/SearchPage';
61+
import { orchestratorTranslations } from '@red-hat-developer-hub/backstage-plugin-orchestrator';
6162

6263
const app = createApp({
6364
apis,
@@ -102,6 +103,10 @@ const app = createApp({
102103
),
103104
},
104105
themes: getThemes(),
106+
__experimentalTranslations: {
107+
availableLanguages: ['en', 'de', 'fr', 'it', 'es'],
108+
resources: [orchestratorTranslations],
109+
},
105110
/* Hardcoded deployment of the Orchestrator Form Widget library in our DEV-only instance.
106111
In a production deployment, the plugin will be loaded dynamically. */
107112
plugins: [orchestratorFormWidgetsPlugin, customAuthProviderPlugin],

workspaces/orchestrator/plugins/orchestrator-backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"@backstage/backend-plugin-api": "^1.3.1",
7171
"@backstage/backend-tasks": "^0.6.1",
7272
"@backstage/catalog-client": "^1.10.0",
73+
"@backstage/core-plugin-api": "^1.10.7",
7374
"@backstage/errors": "^1.2.7",
7475
"@backstage/integration": "^1.17.0",
7576
"@backstage/plugin-catalog-node": "^1.17.0",

workspaces/orchestrator/plugins/orchestrator-common/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"openapi:check": "./scripts/openapi.sh check"
5858
},
5959
"dependencies": {
60+
"@backstage/core-plugin-api": "^1.10.7",
6061
"@backstage/plugin-permission-common": "^0.9.0",
6162
"@backstage/types": "^1.2.1",
6263
"@severlessworkflow/sdk-typescript": "^3.0.3",

workspaces/orchestrator/plugins/orchestrator-form-react/report.api.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { JsonObject } from '@backstage/types';
88
import type { JSONSchema7 } from 'json-schema';
99
import { JSX as JSX_2 } from 'react/jsx-runtime';
1010
import { OrchestratorFormContextProps } from '@red-hat-developer-hub/backstage-plugin-orchestrator-form-api';
11-
import { default as React_2 } from 'react';
11+
import { ReactNode } from 'react';
1212

1313
// @public
14-
export const OrchestratorForm: ({ schema: rawSchema, updateSchema, handleExecute, isExecuting, initialFormData, setAuthTokenDescriptors, }: OrchestratorFormProps) => JSX_2.Element;
14+
export const OrchestratorForm: ({ schema: rawSchema, updateSchema, handleExecute, isExecuting, initialFormData, setAuthTokenDescriptors, t, }: OrchestratorFormProps) => JSX_2.Element;
1515

1616
// @public
1717
export type OrchestratorFormProps = {
@@ -21,14 +21,32 @@ export type OrchestratorFormProps = {
2121
isExecuting: boolean;
2222
handleExecute: (parameters: JsonObject) => Promise<void>;
2323
initialFormData: JsonObject;
24+
t: TranslationFunction;
2425
};
2526

2627
// @public
2728
export const SubmitButton: ({ submitting, handleClick, children, focusOnMount, }: {
2829
submitting: boolean;
2930
handleClick?: () => void;
30-
children: React_2.ReactNode;
31+
children: ReactNode;
3132
focusOnMount?: boolean;
3233
}) => JSX_2.Element;
3334

35+
// Warning: (ae-missing-release-tag) "TranslationFunction" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
36+
//
37+
// @public (undocumented)
38+
export type TranslationFunction = (key: string) => string;
39+
40+
// Warning: (ae-missing-release-tag) "useTranslation" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
41+
//
42+
// @public (undocumented)
43+
export const useTranslation: () => {
44+
t: TranslationFunction;
45+
};
46+
47+
// Warnings were encountered during analysis:
48+
//
49+
// src/hooks/useTranslation.d.ts:1:1 - (ae-undocumented) Missing documentation for "TranslationFunction".
50+
// src/hooks/useTranslation.d.ts:2:22 - (ae-undocumented) Missing documentation for "useTranslation".
51+
3452
```

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/OrchestratorForm.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import get from 'lodash/get';
2525

2626
import { OrchestratorFormContextProps } from '@red-hat-developer-hub/backstage-plugin-orchestrator-form-api';
2727

28+
import { TranslationFunction } from '../hooks/useTranslation';
2829
import generateUiSchema from '../utils/generateUiSchema';
2930
import { StepperContextProvider } from '../utils/StepperContext';
3031
import OrchestratorFormWrapper from './OrchestratorFormWrapper';
@@ -50,6 +51,7 @@ export type OrchestratorFormProps = {
5051
isExecuting: boolean;
5152
handleExecute: (parameters: JsonObject) => Promise<void>;
5253
initialFormData: JsonObject;
54+
t: TranslationFunction;
5355
};
5456

5557
/**
@@ -105,6 +107,7 @@ const OrchestratorForm = ({
105107
isExecuting,
106108
initialFormData,
107109
setAuthTokenDescriptors,
110+
t,
108111
}: OrchestratorFormProps) => {
109112
// make the form a controlled component so the state will remain when moving between steps. see https://rjsf-team.github.io/react-jsonschema-form/docs/quickstart#controlled-component
110113
const [formData, setFormData] = useState<JsonObject>(
@@ -148,7 +151,7 @@ const OrchestratorForm = ({
148151
);
149152

150153
return (
151-
<StepperContextProvider reviewStep={reviewStep}>
154+
<StepperContextProvider reviewStep={reviewStep} t={t}>
152155
{isMultiStep ? (
153156
<OrchestratorFormWrapper
154157
schema={schema}

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/OrchestratorFormStepper.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react';
18-
1917
import Button from '@mui/material/Button';
2018
import Step from '@mui/material/Step';
2119
import StepLabel from '@mui/material/StepLabel';
2220
import Stepper from '@mui/material/Stepper';
2321
import Typography from '@mui/material/Typography';
2422
import { makeStyles } from 'tss-react/mui';
2523

24+
import { useTranslation } from '../hooks/useTranslation';
2625
import { useStepperContext } from '../utils/StepperContext';
2726
import SubmitButton from './SubmitButton';
2827

@@ -59,11 +58,12 @@ const OrchestratorFormStepper = ({
5958
}: {
6059
steps: OrchestratorFormStep[];
6160
}) => {
61+
const { t } = useTranslation();
6262
const { classes } = useStyles();
6363
const { activeStep, reviewStep } = useStepperContext();
6464
const stepsWithReview = [
6565
...steps,
66-
{ content: reviewStep, title: 'Review', key: 'review' },
66+
{ content: reviewStep, title: t('common.review'), key: 'review' },
6767
];
6868

6969
return (
@@ -96,18 +96,20 @@ const OrchestratorFormStepper = ({
9696
};
9797

9898
export const OrchestratorFormToolbar = () => {
99+
const { t } = useTranslation();
99100
const { activeStep, handleBack, isValidating } = useStepperContext();
100101
const { classes } = useStyles();
102+
101103
return (
102104
<div className={classes.footer}>
103105
<Button
104106
disabled={activeStep === 0}
105107
onClick={handleBack}
106108
className={classes.regularButton}
107109
>
108-
Back
110+
{t('common.back')}
109111
</Button>
110-
<SubmitButton submitting={isValidating}>Next</SubmitButton>
112+
<SubmitButton submitting={isValidating}>{t('common.next')}</SubmitButton>
111113
</div>
112114
);
113115
};

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/OrchestratorFormWrapper.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react';
17+
import { useMemo, useState } from 'react';
1818

1919
import { ErrorPanel } from '@backstage/core-components';
2020
import { JsonObject } from '@backstage/types';
@@ -32,6 +32,7 @@ import {
3232
useOrchestratorFormApiOrDefault,
3333
} from '@red-hat-developer-hub/backstage-plugin-orchestrator-form-api';
3434

35+
import { useTranslation } from '../hooks/useTranslation';
3536
import { getActiveStepKey } from '../utils/getSortedStepEntries';
3637
import { useStepperContext } from '../utils/StepperContext';
3738
import useValidator from '../utils/useValidator';
@@ -47,20 +48,19 @@ const MuiForm = withTheme<
4748
const FormComponent = (decoratorProps: FormDecoratorProps) => {
4849
const formContext = decoratorProps.formContext;
4950

50-
const [extraErrors, setExtraErrors] = React.useState<
51+
const [extraErrors, setExtraErrors] = useState<
5152
ErrorSchema<JsonObject> | undefined
5253
>();
5354
const numStepsInMultiStepSchema = formContext?.numStepsInMultiStepSchema;
5455
const isMultiStep = numStepsInMultiStepSchema !== undefined;
5556
const { handleNext, activeStep, handleValidateStarted, handleValidateEnded } =
5657
useStepperContext();
57-
const [validationError, setValidationError] = React.useState<
58-
Error | undefined
59-
>();
58+
const [validationError, setValidationError] = useState<Error | undefined>();
6059
const validator = useValidator(isMultiStep);
60+
const { t } = useTranslation();
6161

6262
if (!formContext) {
63-
return <div>Form decorator must provide context data.</div>;
63+
return <div>{t('formDecorator.error')}</div>;
6464
}
6565

6666
const {
@@ -148,7 +148,7 @@ const FormComponent = (decoratorProps: FormDecoratorProps) => {
148148
const OrchestratorFormWrapper = (props: OrchestratorFormContextProps) => {
149149
const formApi = useOrchestratorFormApiOrDefault();
150150

151-
const NewComponent = React.useMemo(() => {
151+
const NewComponent = useMemo(() => {
152152
const formDecorator = formApi.getFormDecorator();
153153
return formDecorator(FormComponent);
154154
}, [formApi]);

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/ReviewStep.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import React from 'react';
17+
import { useMemo } from 'react';
1818

1919
import { Content, StructuredMetadataTable } from '@backstage/core-components';
2020
import { JsonObject } from '@backstage/types';
@@ -25,6 +25,7 @@ import Paper from '@mui/material/Paper';
2525
import type { JSONSchema7 } from 'json-schema';
2626
import { makeStyles } from 'tss-react/mui';
2727

28+
import { useTranslation } from '../hooks/useTranslation';
2829
import generateReviewTableData from '../utils/generateReviewTableData';
2930
import { useStepperContext } from '../utils/StepperContext';
3031
import SubmitButton from './SubmitButton';
@@ -66,9 +67,11 @@ const ReviewStep = ({
6667
data: JsonObject;
6768
handleExecute: () => void;
6869
}) => {
70+
const { t } = useTranslation();
71+
6972
const { classes } = useStyles();
7073
const { handleBack } = useStepperContext();
71-
const displayData = React.useMemo<JsonObject>(() => {
74+
const displayData = useMemo<JsonObject>(() => {
7275
return generateReviewTableData(schema, data);
7376
}, [schema, data]);
7477

@@ -83,14 +86,14 @@ const ReviewStep = ({
8386
className={classes.backButton}
8487
disabled={busy}
8588
>
86-
Back
89+
{t('common.back')}
8790
</Button>
8891
<SubmitButton
8992
handleClick={handleExecute}
9093
submitting={busy}
9194
focusOnMount
9295
>
93-
Run
96+
{t('common.run')}
9497
</SubmitButton>
9598
</div>
9699
</Paper>

workspaces/orchestrator/plugins/orchestrator-form-react/src/components/SingleStepForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
import React from 'react';
16+
import { useMemo } from 'react';
1717

1818
import { OrchestratorFormContextProps } from '@red-hat-developer-hub/backstage-plugin-orchestrator-form-api';
1919

@@ -35,7 +35,7 @@ type SingleStepFormProps = Pick<
3535
>;
3636

3737
const SingleStepForm = (props: SingleStepFormProps) => {
38-
const steps = React.useMemo<OrchestratorFormStep[]>(() => {
38+
const steps = useMemo<OrchestratorFormStep[]>(() => {
3939
return [
4040
{
4141
title: props.schema.title ?? 'Inputs',

0 commit comments

Comments
 (0)