Skip to content

Commit

Permalink
i18n support in devconsole helm components
Browse files Browse the repository at this point in the history
  • Loading branch information
vikram-raj committed Nov 11, 2020
1 parent c8489f4 commit fb21aaf
Show file tree
Hide file tree
Showing 33 changed files with 420 additions and 200 deletions.
59 changes: 57 additions & 2 deletions frontend/packages/dev-console/locales/en/devconsole.json
Expand Up @@ -16,8 +16,64 @@
"Success Threshold must be greater than or equal to 1.": "Success Threshold must be greater than or equal to 1.",
"Path must start with /.": "Path must start with /.",
"Required": "Required",
"Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.": "Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.",
"Helm Releases": "Helm Releases",
"Helm Release Details": "Helm Release Details",
"Resources": "Resources",
"Revision History": "Revision History",
"Release Notes": "Release Notes",
"Unable to load Helm Release history": "Unable to load Helm Release history",
"Helm Release history": "Helm Release history",
"Revision": "Revision",
"Updated": "Updated",
"Status": "Status",
"Chart Name": "Chart Name",
"Chart Version": "Chart Version",
"App Version": "App Version",
"Description": "Description",
"confirmModalRollbackHelmReleaseKey": "Are you sure you want to rollback <1>{{releaseName}}</1> to <4>Revision {{revision}}</4>?",
"Rollback to Revision {{revision}}": "Rollback to Revision {{revision}}",
"Rollback": "Rollback",
"No Release Notes Available": "No Release Notes Available",
"Release Notes are not available for this Helm Chart.": "Release Notes are not available for this Helm Chart.",
"Resources by name": "Resources by name",
"Name": "Name",
"Type": "Type",
"Created": "Created",
"No Resources Found": "No Resources Found",
"pods": "pods",
"{{chartVersion}} provided by {{provider}}": "{{chartVersion}} provided by {{provider}}",
"Change Chart Version?": "Change Chart Version?",
"Are you sure you want to change the chart version from <2>{{currentVersion}}</2> to <4>{{newVersion}}</4>? ": "Are you sure you want to change the chart version from <2>{{currentVersion}}</2> to <4>{{newVersion}}</4>? ",
"All data entered for version <1>{{currentVersion}}</1> will be reset": "All data entered for version <1>{{currentVersion}}</1> will be reset",
"Proceed": "Proceed",
"Select the Chart Version.": "Select the Chart Version.",
"Select the version to upgrade to.": "Select the version to upgrade to.",
"No versions available": "No versions available",
"Helm Chart": "Helm Chart",
"For more information on the chart, refer to this <2>README</2>": "For more information on the chart, refer to this <2>README</2>",
"Helm chart cannot be installed": "Helm chart cannot be installed",
"The Helm chart is currently unavailable. {{chartError}}": "The Helm chart is currently unavailable. {{chartError}}",
"Release Name": "Release Name",
"A unique name for the Helm Chart release.": "A unique name for the Helm Chart release.",
"Select the version to rollback <1>{{releaseName}}</1> to, from the table below:": "Select the version to rollback <1>{{releaseName}}</1> to, from the table below:",
"CustomResources": "CustomResources",
" / App Version {{appVersion}}": " / App Version {{appVersion}}",
" (Provided by {{chartRepoName}})": " (Provided by {{chartRepoName}})",
"Install Helm Chart": "Install Helm Chart",
"The Helm chart can be installed by completing the form. Default values may be provided by the Helm chart authors.": "The Helm chart can be installed by completing the form. Default values may be provided by the Helm chart authors.",
"The Helm chart can be installed by manually entering YAML or JSON definitions.": "The Helm chart can be installed by manually entering YAML or JSON definitions.",
"Upgrade Helm Release": "Upgrade Helm Release",
"Upgrade by selecting a new chart version or manually changing the form values.": "Upgrade by selecting a new chart version or manually changing the form values.",
"Upgrade by selecting a new chart version or manually changing YAML.": "Upgrade by selecting a new chart version or manually changing YAML.",
"Rollback Helm Release": "Rollback Helm Release",
"Errors in the Form - {{errorsText}}": "Errors in the Form - {{errorsText}}",
"Invalid YAML - {{err}}": "Invalid YAML - {{err}}",
"README": "README",
"Select a project to view the list of Helm Releases": "Select a project to view the list of Helm Releases",
"Unable to load Helm Releases": "Unable to load Helm Releases",
"No Helm Releases found": "No Helm Releases found",
"Install a Helm Chart from the developer catalog": "Install a Helm Chart from the developer catalog",
"Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.": "Note: Some fields may not be represented in this form view. Please select \"YAML view\" for full control.",
"Minimum Pods": "Minimum Pods",
"Maximum Pods": "Maximum Pods",
"CPU": "CPU",
Expand Down Expand Up @@ -189,7 +245,6 @@
"A {{deploymentLabel}} enables declarative updates for Pods and ReplicaSets.": "A {{deploymentLabel}} enables declarative updates for Pods and ReplicaSets.",
"A {{deploymentConfigLabel}} defines the template for a pod and manages deploying new images or configuration changes.": "A {{deploymentConfigLabel}} defines the template for a pod and manages deploying new images or configuration changes.",
"A type of deployment that enables Serverless scaling to 0 when idle.": "A type of deployment that enables Serverless scaling to 0 when idle.",
"Resources": "Resources",
"Select the resource type to generate": "Select the resource type to generate",
"Replicas must be an Integer.": "Replicas must be an Integer.",
"Replicas must be greater than or equal to 0.": "Replicas must be greater than or equal to 0.",
Expand Down
Expand Up @@ -6,6 +6,7 @@ import { safeDump, safeLoad } from 'js-yaml';
import { Formik } from 'formik';
import { Helmet } from 'react-helmet';
import { RouteComponentProps } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { history, LoadingBox } from '@console/internal/components/utils';
import { coFetchJSON } from '@console/internal/co-fetch';
import { PageBody } from '@console/shared';
Expand Down Expand Up @@ -58,6 +59,7 @@ const HelmInstallUpgradePage: React.FunctionComponent<HelmInstallUpgradePageProp
const helmChartRepoName = searchParams.get('chartRepoName');
const helmActionOrigin = searchParams.get('actionOrigin') as HelmActionOrigins;

const { t } = useTranslation();
const [chartData, setChartData] = React.useState<HelmChart>(null);
const [chartName, setChartName] = React.useState<string>('');
const [chartVersion, setChartVersion] = React.useState<string>('');
Expand All @@ -79,10 +81,11 @@ const HelmInstallUpgradePage: React.FunctionComponent<HelmInstallUpgradePageProp
helmAction,
initialReleaseName,
namespace,
t,
helmActionOrigin,
initialChartURL,
),
[helmAction, helmActionOrigin, initialChartURL, initialReleaseName, namespace],
[helmAction, helmActionOrigin, initialChartURL, initialReleaseName, namespace, t],
);

React.useEffect(() => {
Expand Down Expand Up @@ -155,14 +158,18 @@ const HelmInstallUpgradePage: React.FunctionComponent<HelmInstallUpgradePageProp
if (validFormData) {
valuesObj = formData;
} else {
actions.setStatus({ submitError: `Errors in the Form - ${ajv.errorsText()}` });
actions.setStatus({
submitError: t('devconsole~Errors in the Form - {{errorsText}}', {
errorsText: ajv.errorsText(),
}),
});
return;
}
} else if (yamlData) {
try {
valuesObj = safeLoad(yamlData);
} catch (err) {
actions.setStatus({ submitError: `Invalid YAML - ${err}` });
actions.setStatus({ submitError: t('devconsole~Invalid YAML - {{err}}', { err }) });
return;
}
}
Expand Down Expand Up @@ -223,7 +230,7 @@ const HelmInstallUpgradePage: React.FunctionComponent<HelmInstallUpgradePageProp
initialValues={initialValues}
onSubmit={handleSubmit}
onReset={history.goBack}
validationSchema={getHelmActionValidationSchema(helmAction)}
validationSchema={getHelmActionValidationSchema(helmAction, t)}
>
{(formikProps) => (
<HelmInstallUpgradeForm
Expand Down
@@ -1,4 +1,5 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import {
ModalTitle,
ModalBody,
Expand All @@ -12,14 +13,17 @@ type HelmReadmeModalProps = {
};
type Props = HelmReadmeModalProps & ModalComponentProps;

const HelmReadmeModal: React.FunctionComponent<Props> = ({ readme, close }) => (
<div className="modal-content">
<ModalTitle close={close}>README</ModalTitle>
<ModalBody>
<SyncMarkdownView content={readme} />
</ModalBody>
</div>
);
const HelmReadmeModal: React.FunctionComponent<Props> = ({ readme, close }) => {
const { t } = useTranslation();
return (
<div className="modal-content">
<ModalTitle close={close}>{t('devconsole~README')}</ModalTitle>
<ModalBody>
<SyncMarkdownView content={readme} />
</ModalBody>
</div>
);
};

export const helmReadmeModalLauncher = createModalLauncher<Props>(HelmReadmeModal);
export default HelmReadmeModal;
@@ -1,6 +1,7 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import Helmet from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { PageHeading } from '@console/internal/components/utils';
import { withStartGuide } from '@console/internal/components/start-guide';
import CreateProjectListPage from '../projects/CreateProjectListPage';
Expand All @@ -10,32 +11,36 @@ import HelmReleaseList from './list/HelmReleaseList';
type HelmReleaseListPageProps = RouteComponentProps<{ ns: string }>;

const PageContents: React.FC<HelmReleaseListPageProps> = (props) => {
const { t } = useTranslation();
const {
match: {
params: { ns: namespace },
},
} = props;
return namespace ? (
<div>
<PageHeading title="Helm Releases" />
<PageHeading title={t('devconsole~Helm Releases')} />
<HelmReleaseList namespace={namespace} />
</div>
) : (
<CreateProjectListPage title="Helm Releases">
Select a project to view the list of Helm Releases
<CreateProjectListPage title={t('devconsole~Helm Releases')}>
{t('devconsole~Select a project to view the list of Helm Releases')}
</CreateProjectListPage>
);
};

const PageContentsWithStartGuide = withStartGuide(PageContents);

export const HelmReleaseListPage: React.FC<HelmReleaseListPageProps> = (props) => (
<NamespacedPage variant={NamespacedPageVariants.light} hideApplications>
<Helmet>
<title>Helm Releases</title>
</Helmet>
<PageContentsWithStartGuide {...props} />
</NamespacedPage>
);
export const HelmReleaseListPage: React.FC<HelmReleaseListPageProps> = (props) => {
const { t } = useTranslation();
return (
<NamespacedPage variant={NamespacedPageVariants.light} hideApplications>
<Helmet>
<title>{t('devconsole~Helm Releases')}</title>
</Helmet>
<PageContentsWithStartGuide {...props} />
</NamespacedPage>
);
};

export default HelmReleaseListPage;
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import Helmet from 'react-helmet';
import { Formik } from 'formik';
import { RouteComponentProps } from 'react-router';
import { useTranslation } from 'react-i18next';
import { PageBody } from '@console/shared';
import { coFetchJSON } from '@console/internal/co-fetch';
import { history, getQueryArgument } from '@console/internal/components/utils';
Expand All @@ -21,13 +22,14 @@ type HelmRollbackFormData = {
};

const HelmReleaseRollbackPage: React.FC<HelmReleaseRollbackPageProps> = ({ match }) => {
const { t } = useTranslation();
const { releaseName, ns: namespace } = match.params;
const actionOrigin = getQueryArgument('actionOrigin') as HelmActionOrigins;
const [releaseHistory, setReleaseHistory] = React.useState<HelmRelease[]>(null);

const config = React.useMemo(
() => getHelmActionConfig(HelmActionType.Rollback, releaseName, namespace, actionOrigin),
[actionOrigin, namespace, releaseName],
() => getHelmActionConfig(HelmActionType.Rollback, releaseName, namespace, t, actionOrigin),
[actionOrigin, namespace, releaseName, t],
);

React.useEffect(() => {
Expand Down
@@ -1,3 +1,4 @@
import { TFunction } from 'i18next';
import {
OtherReleaseStatuses,
releaseStatusReducer,
Expand All @@ -20,6 +21,8 @@ import {
mockRedhatHelmChartData,
} from './helm-release-mock-data';

const t = (key: TFunction) => key;

describe('Helm Releases Utils', () => {
it('should return deployed or failed status for a helm release', () => {
const release = mockHelmReleases[0];
Expand Down Expand Up @@ -70,13 +73,16 @@ describe('Helm Releases Utils', () => {
});

it('should return the chart versions, concatenated with the App Version, available for the helm chart', () => {
const chartVersions = getChartVersions(mockHelmChartData);
const chartVersions = getChartVersions(mockHelmChartData, t);
expect(chartVersions).toEqual({
'1.0.1--ibm-helm-repo': '1.0.1 / App Version 3.10.5 (Provided by Ibm Helm Repo)',
'1.0.2--ibm-helm-repo': '1.0.2 (Provided by Ibm Helm Repo)',
'1.0.3--ibm-helm-repo': '1.0.3 / App Version 3.12 (Provided by Ibm Helm Repo)',
'1.0.1--redhat-helm-repo': '1.0.1 / App Version 3.10.5 (Provided by Redhat Helm Repo)',
'1.0.2--redhat-helm-repo': '1.0.2 (Provided by Redhat Helm Repo)',
'1.0.1--ibm-helm-repo':
'1.0.1devconsole~ / App Version {{appVersion}}devconsole~ (Provided by {{chartRepoName}})',
'1.0.1--redhat-helm-repo':
'1.0.1devconsole~ / App Version {{appVersion}}devconsole~ (Provided by {{chartRepoName}})',
'1.0.2--ibm-helm-repo': '1.0.2devconsole~ (Provided by {{chartRepoName}})',
'1.0.2--redhat-helm-repo': '1.0.2devconsole~ (Provided by {{chartRepoName}})',
'1.0.3--ibm-helm-repo':
'1.0.3devconsole~ / App Version {{appVersion}}devconsole~ (Provided by {{chartRepoName}})',
});
});

Expand Down
@@ -1,6 +1,7 @@
import * as React from 'react';
import * as _ from 'lodash';
import { match as RMatch } from 'react-router';
import { useTranslation } from 'react-i18next';
import {
navFactory,
LoadingBox,
Expand Down Expand Up @@ -44,6 +45,7 @@ export const LoadedHelmReleaseDetails: React.FC<LoadedHelmReleaseDetailsProps> =
secret,
helmReleaseData,
}) => {
const { t } = useTranslation();
const namespace = match.params.ns;
if (!helmReleaseData || !secret || (!secret.loaded && _.isEmpty(secret.loadError))) {
return <LoadingBox />;
Expand Down Expand Up @@ -92,28 +94,28 @@ export const LoadedHelmReleaseDetails: React.FC<LoadedHelmReleaseDetailsProps> =
customData={helmReleaseData}
breadcrumbsFor={() => [
{
name: `Helm Releases`,
name: t('devconsole~Helm Releases'),
path: `/helm-releases/ns/${namespace}`,
},
{ name: `Helm Release Details`, path: `${match.url}` },
{ name: t('devconsole~Helm Release Details'), path: `${match.url}` },
]}
title={title}
kind={SecretReference}
pages={[
navFactory.details(HelmReleaseOverview),
{
href: 'resources',
name: 'Resources',
name: t('devconsole~Resources'),
component: HelmReleaseResources,
},
{
href: 'history',
name: 'Revision History',
name: t('devconsole~Revision History'),
component: HelmReleaseHistory,
},
{
href: 'releasenotes',
name: 'Release Notes',
name: t('devconsole~Release Notes'),
component: HelmReleaseNotes,
},
]}
Expand Down
Expand Up @@ -9,6 +9,14 @@ import HelmReleaseDetails, { LoadedHelmReleaseDetails } from '../HelmReleaseDeta
let helmReleaseDetailsProps: React.ComponentProps<typeof HelmReleaseDetails>;
let loadedHelmReleaseDetailsProps: React.ComponentProps<typeof LoadedHelmReleaseDetails>;

jest.mock('react-i18next', () => {
const reactI18next = require.requireActual('react-i18next');
return {
...reactI18next,
useTranslation: () => ({ t: (key) => key }),
};
});

describe('HelmReleaseDetails', () => {
beforeEach(() => {
helmReleaseDetailsProps = {
Expand Down
@@ -1,5 +1,6 @@
import * as React from 'react';
import { match as RMatch } from 'react-router';
import { useTranslation } from 'react-i18next';
import { SortByDirection } from '@patternfly/react-table';
import { useDeepCompareMemoize } from '@console/shared';
import { K8sResourceKind } from '@console/internal/module/k8s';
Expand All @@ -24,6 +25,7 @@ const HelmReleaseHistory: React.FC<HelmReleaseHistoryProps> = ({ match, obj }) =
const [loadError, setLoadError] = React.useState<string>();
const [revisions, setRevisions] = React.useState([]);
const memoizedObj = useDeepCompareMemoize(obj);
const { t } = useTranslation();

React.useEffect(() => {
let destroyed = false;
Expand All @@ -38,16 +40,16 @@ const HelmReleaseHistory: React.FC<HelmReleaseHistoryProps> = ({ match, obj }) =
.catch((err) => {
if (!destroyed) {
setRevisionsLoaded(true);
setLoadError(err.message || 'Unable to load Helm Release history');
setLoadError(err.message || t('devconsole~Unable to load Helm Release history'));
}
});
return () => {
destroyed = true;
};
}, [helmReleaseName, namespace, memoizedObj]);
}, [helmReleaseName, namespace, memoizedObj, t]);

if (loadError) {
return <StatusBox loaded loadError={loadError} label="Helm Release history" />;
return <StatusBox loaded loadError={loadError} label={t('devconsole~Helm Release history')} />;
}

return (
Expand All @@ -57,7 +59,7 @@ const HelmReleaseHistory: React.FC<HelmReleaseHistoryProps> = ({ match, obj }) =
sortBy="version"
sortOrder={SortByDirection.desc}
resourceRow={HelmReleaseHistoryRow}
resourceHeader={HelmReleaseHistoryHeader}
resourceHeader={HelmReleaseHistoryHeader(t)}
/>
);
};
Expand Down

0 comments on commit fb21aaf

Please sign in to comment.