From 1f81592b5c7bb117188bbdcc77deb528d7da1c89 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Thu, 14 Jan 2021 15:25:58 -0500 Subject: [PATCH] adds translation linting and addresses issues the linter found --- awx/ui_next/.eslintrc | 5 +++-- awx/ui_next/package-lock.json | 15 +++++++++++++ awx/ui_next/package.json | 1 + .../CodeMirrorInput/VariablesDetail.jsx | 5 +++-- .../CodeMirrorInput/VariablesDetail.test.jsx | 22 ++++++++++++------- .../src/components/JobList/JobList.jsx | 2 +- .../src/components/JobList/JobListItem.jsx | 4 +++- awx/ui_next/src/components/Lookup/Lookup.jsx | 2 +- .../NotificationList/NotificationListItem.jsx | 2 +- .../components/PromptDetail/PromptDetail.jsx | 2 +- .../ScheduleList/ScheduleListItem.jsx | 2 +- .../ApplicationsList/ApplicationListItem.jsx | 2 +- .../CredentialList/CredentialListItem.jsx | 2 +- .../CredentialTypeListItem.jsx | 2 +- .../shared/DashboardTemplateList.jsx | 2 +- .../shared/DashboardTemplateListItem.jsx | 5 ++++- .../screens/Host/HostGroups/HostGroupItem.jsx | 2 +- .../screens/Host/HostList/HostListItem.jsx | 2 +- .../InstanceGroupListItem.jsx | 2 +- .../Instances/InstanceListItem.jsx | 2 +- .../InventoryGroupHostListItem.jsx | 2 +- .../InventoryGroups/InventoryGroupItem.jsx | 2 +- .../InventoryHostGroupItem.jsx | 2 +- .../InventoryHosts/InventoryHostItem.jsx | 2 +- .../InventoryRelatedGroupListItem.jsx | 2 +- .../InventorySourceListItem.jsx | 2 +- .../SmartInventoryDetail.jsx | 2 +- .../NotificationTemplateListItem.jsx | 5 ++++- .../shared/CustomMessagesSubForm.jsx | 21 +++++++++++------- .../OrganizationList/OrganizationList.jsx | 2 +- .../OrganizationTeamListItem.jsx | 2 +- .../ProjectJobTemplatesListItem.jsx | 2 +- .../Project/ProjectList/ProjectListItem.jsx | 2 +- .../shared/ProjectSubForms/ArchiveSubForm.jsx | 12 ++++++++-- .../shared/ProjectSubForms/GitSubForm.jsx | 20 ++++++++++++----- .../shared/ProjectSubForms/SvnSubForm.jsx | 12 +++++++--- .../screens/Team/TeamList/TeamListItem.jsx | 2 +- .../Template/TemplateList/TemplateList.jsx | 2 +- .../TemplateList/TemplateListItem.jsx | 5 ++++- .../Modals/LinkModals/LinkDeleteModal.jsx | 2 +- .../Template/shared/JobTemplateForm.test.jsx | 8 +++++-- .../Template/shared/WebhookSubForm.jsx | 2 +- .../Template/shared/WebhookSubForm.test.jsx | 8 +++++-- .../shared/WorkflowJobTemplateForm.test.jsx | 8 +++++-- .../src/screens/User/UserList/UserList.jsx | 2 +- .../screens/User/UserList/UserListItem.jsx | 2 +- 46 files changed, 146 insertions(+), 70 deletions(-) diff --git a/awx/ui_next/.eslintrc b/awx/ui_next/.eslintrc index e2bf9305bd..c93c2a8992 100644 --- a/awx/ui_next/.eslintrc +++ b/awx/ui_next/.eslintrc @@ -8,8 +8,8 @@ "modules": true } }, - "plugins": ["react-hooks", "jsx-a11y"], - "extends": ["airbnb", "prettier", "prettier/react", "plugin:jsx-a11y/strict"], + "plugins": ["react-hooks", "jsx-a11y", "i18next"], + "extends": ["airbnb", "prettier", "prettier/react", "plugin:jsx-a11y/strict", "plugin:i18next/recommended"], "settings": { "react": { "version": "16.5.2" @@ -24,6 +24,7 @@ "window": true }, "rules": { + "i18next/no-literal-string": [2, {"markupOnly": true, "ignoreAttribute": ["to", "streamType", "path", "component", "variant", "key", "position", "promptName", "color","promptId", "headingLevel", "size", "target", "autoComplete","trigger", "from", "name", "fieldId", "css", "gutter", "dataCy", "tooltipMaxWidth", "mode", "aria-labelledby","aria-hidden","sortKey", "ouiaId", "credentialTypeNamespace", "link", "value", "credentialTypeKind", "linkTo", "scrollToAlignment", "displayKey", "sortedColumnKey", "maxHeight", "role", "aria-haspopup", "dropDirection", "resizeOrientation", "src", "theme"], "ignore":["Ansible", "Tower", "JSON", "YAML", "lg", "START"],"ignoreComponent":["code", "Omit","PotentialLink", "TypeRedirect", "Radio", "RunOnRadio", "NodeTypeLetter", "SelectableItem", "Dash"], "ignoreCallee": ["describe"] }], "camelcase": "off", "arrow-parens": "off", "comma-dangle": "off", diff --git a/awx/ui_next/package-lock.json b/awx/ui_next/package-lock.json index a64e834f55..70e18e4165 100644 --- a/awx/ui_next/package-lock.json +++ b/awx/ui_next/package-lock.json @@ -7172,6 +7172,15 @@ "lodash": "^4.17.15" } }, + "eslint-plugin-i18next": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-i18next/-/eslint-plugin-i18next-5.0.0.tgz", + "integrity": "sha512-ixbgSMrSb0dZsO6WPElg4JvPiQKLDA3ZpBuayxToADan1TKcbzKXT2A42Vyc0lEDhJRPL6uZnmm8vPjODDJypg==", + "dev": true, + "requires": { + "requireindex": "~1.1.0" + } + }, "eslint-plugin-import": { "version": "2.22.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", @@ -15163,6 +15172,12 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI=", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", diff --git a/awx/ui_next/package.json b/awx/ui_next/package.json index b052a3183f..7eb3759e74 100644 --- a/awx/ui_next/package.json +++ b/awx/ui_next/package.json @@ -43,6 +43,7 @@ "eslint-config-airbnb": "^17.1.0", "eslint-config-prettier": "^5.0.0", "eslint-import-resolver-webpack": "0.11.1", + "eslint-plugin-i18next": "^5.0.0", "eslint-plugin-import": "^2.14.0", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-react": "^7.11.1", diff --git a/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.jsx b/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.jsx index feb3ebb0b7..b5501fb0b7 100644 --- a/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.jsx +++ b/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.jsx @@ -1,6 +1,7 @@ import 'styled-components/macro'; import React, { useState, useEffect } from 'react'; import { node, number, oneOfType, shape, string, arrayOf } from 'prop-types'; +import { Trans, withI18n } from '@lingui/react'; import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core'; import { DetailName, DetailValue } from '../DetailList'; import MultiButtonToggle from '../MultiButtonToggle'; @@ -111,7 +112,7 @@ function VariablesDetail({ dataCy, helpText, value, label, rows, fullHeight }) { css="color: var(--pf-global--danger-color--100); font-size: var(--pf-global--FontSize--sm" > - Error: {error.message} + Error: {error.message} )} @@ -131,4 +132,4 @@ VariablesDetail.defaultProps = { helpText: '', }; -export default VariablesDetail; +export default withI18n()(VariablesDetail); diff --git a/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.test.jsx b/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.test.jsx index edb83d3515..9cf080e1ed 100644 --- a/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.test.jsx +++ b/awx/ui_next/src/components/CodeMirrorInput/VariablesDetail.test.jsx @@ -1,13 +1,13 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { shallow, mount } from 'enzyme'; +import { mountWithContexts } from '../../../testUtils/enzymeHelpers'; import VariablesDetail from './VariablesDetail'; jest.mock('../../api'); describe('', () => { test('should render readonly CodeMirrorInput', () => { - const wrapper = shallow( + const wrapper = mountWithContexts( ); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); @@ -18,7 +18,7 @@ describe('', () => { }); test('should detect JSON', () => { - const wrapper = shallow( + const wrapper = mountWithContexts( ); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); @@ -28,7 +28,7 @@ describe('', () => { }); test('should convert between modes', () => { - const wrapper = shallow( + const wrapper = mountWithContexts( ); wrapper.find('MultiButtonToggle').invoke('onChange')('javascript'); @@ -43,7 +43,9 @@ describe('', () => { }); test('should render label and value= --- when there are no values', () => { - const wrapper = shallow(); + const wrapper = mountWithContexts( + + ); expect(wrapper.find('VariablesDetail___StyledCodeMirrorInput').length).toBe( 1 ); @@ -51,7 +53,7 @@ describe('', () => { }); test('should update value if prop changes', () => { - const wrapper = mount( + const wrapper = mountWithContexts( ); act(() => { @@ -67,13 +69,17 @@ describe('', () => { }); test('should default yaml value to "---"', () => { - const wrapper = shallow(); + const wrapper = mountWithContexts( + + ); const input = wrapper.find('VariablesDetail___StyledCodeMirrorInput'); expect(input.prop('value')).toEqual('---'); }); test('should default empty json to "{}"', () => { - const wrapper = mount(); + const wrapper = mountWithContexts( + + ); act(() => { wrapper.find('MultiButtonToggle').invoke('onChange')('javascript'); }); diff --git a/awx/ui_next/src/components/JobList/JobList.jsx b/awx/ui_next/src/components/JobList/JobList.jsx index f21e8bb15b..f4a39e839a 100644 --- a/awx/ui_next/src/components/JobList/JobList.jsx +++ b/awx/ui_next/src/components/JobList/JobList.jsx @@ -258,7 +258,7 @@ function JobList({ i18n, defaultParams, showTypeColumn = false }) { key="delete" onDelete={handleJobDelete} itemsToDelete={selected} - pluralizedItemName="Jobs" + pluralizedItemName={i18n._(t`Jobs`)} />, - {job.id} — {job.name} + {job.id} {job.name} diff --git a/awx/ui_next/src/components/Lookup/Lookup.jsx b/awx/ui_next/src/components/Lookup/Lookup.jsx index 2cfc284af8..d5d86b9f4d 100644 --- a/awx/ui_next/src/components/Lookup/Lookup.jsx +++ b/awx/ui_next/src/components/Lookup/Lookup.jsx @@ -103,7 +103,7 @@ function Lookup(props) {