diff --git a/.gitignore b/.gitignore index 5bf261e7a..bf3be24d4 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ storybook-static .build_cache .eslintcache .cache* + +# Old locale files +locales/**/*_old.json diff --git a/locales/en/common.json b/locales/en/common.json index 3379ebef0..79373f6ab 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1,13 +1,16 @@ { + "ARCHIVAL_PERIOD": "Archival Period", "AriaLabels": { "MAXIMUM_AGE": "Maximum age value", "MAXIMUM_AGE_UNITS_INPUT": "Maximum age units input", "MAXIMUM_SIZE": "Maximum size value", "MAXIMUM_SIZE_UNITS_INPUT": "Maximum size units input" }, + "AUTOMATED_RULES": "Automated Rules", "BETA": "BETA", "CANCEL": "Cancel", "CARD_TYPE": "Card type", + "CLEAN": "Clean", "CLEAR": "Clear", "CLEAR_FILTERS": "Clear all filters", "CLEAR_RECENT": "Clear recent", @@ -20,17 +23,23 @@ "DELETE": "Delete", "DESCRIPTION": "Description", "DEVELOPMENT": "DEVELOPMENT", + "DISABLE": "Disable", + "DONOT_ASK_AGAIN": "Don't ask me again", "DOWNLOAD": "Download", "EDIT": "Edit", + "ENABLED": "Enabled", + "EVENT_SPECIFIER": "Event Specifier", "FILTER_NAME": "Name", "FILTER_TOPIC": "Topic", "HELP": "Help", "HOUR": "Hour", "HOUR_one": "Hour", "HOUR_other": "Hours", - "MAXIMUM_AGE": "Maximum age", + "INITIAL_DELAY": "Initial Delay", + "MATCH_EXPRESSION": "Match Expression", + "MAXIMUM_AGE": "Maximum Age", "MAXIMUM_AGE_HELPER_TEXT": "The maximum age of Recording data stored to disk.", - "MAXIMUM_SIZE": "Maximum size", + "MAXIMUM_SIZE": "Maximum Size", "MAXIMUM_SIZE_HELPER_TEXT": "The maximum size of Recording data saved to disk.", "MERIDIEM_AM": "AM", "MERIDIEM_PM": "PM", @@ -39,7 +48,9 @@ "MINUTE_other": "Minutes", "N/A": "N/A", "NAME": "Name", + "NO_DESCRIPTION": "No description", "OK": "OK", + "PRESERVED_ARCHIVES": "Preserved Archives", "PRODUCTION": "PRODUCTION", "REMOVE": "Remove", "RENAME": "Rename", diff --git a/locales/en/public.json b/locales/en/public.json index d03e4adc4..aadaded3a 100644 --- a/locales/en/public.json +++ b/locales/en/public.json @@ -146,6 +146,26 @@ "POPOVER": "automated-analysis-description-popover" } }, + "CreateRule": { + "ABOUT": "Automated Rules are configurations that instruct Cryostat to create JDK Flight Recordings on matching Target JVM applications. Each Automated Rule specifies parameters for which Event Template to use, how much data should be kept in the application Recording buffer, and how frequently Cryostat should copy the application Recording buffer into Cryostat's own archived storage.", + "ARCHIVAL_PERIOD_HELPER_TEXT": "Time between copies of active Recording data being pulled into Cryostat archive storage.", + "DESCRIPTION_HELPER_TEXT": "Enter a rule description. This is only used for display purposes to aid in identifying rules and their intentions.", + "ENABLE_SWITCH_HELPER_TEXT": "Rules take effect when created if enabled and will be matched against all discovered target applications immediately. When new target applications appear they are checked against all enabled rules. Disabled rules have no effect but are available to be enabled in the future.", + "EVALUATING_EXPRESSION": "Evaluating Match Expression...", + "FAILING_EVALUATION": "The expression matching failed.", + "INITIAL_DELAY_HELPER_TEXT": "Initial delay before archiving starts. The first archived copy will be made this long after the Recording is started. The second archived copy will occur one Archival period later.", + "MATCH_EXPRESSION_HELPER_TEXT": "Enter a Match Expression. This is a Java-like code snippet that is evaluated against each target application to determine whether the rule should be applied.", + "MATCH_EXPRESSION_HINT_BODY": "Try an expression like:", + "MATCH_EXPRESSION_HINT_MODAL_HEADER": "Match Expression hint", + "MAXAGE_HELPER_TEXT": "The maximum age of Recording data retained in the target application's Recording buffer.", + "MAXSIZE_HELPER_TEXT": "The maximum size of Recording data retained in the target application's Recording buffer.", + "NAME_HELPER_TEXT": "Enter a rule name.", + "NAME_HINT": "A rule name can contain only letters, numbers, and underscores.", + "PRESERVED_ARCHIVES_HELPER_TEXT": "The number of Archived Recording copies to preserve in archives for each target application affected by this rule.", + "TEMPLATE_HELPER_TEXT": "The Event Template to be applied by this Rule against matching target applications.", + "TEMPLATE_HINT": "A Template must be selected.", + "WARNING_NO_MATCH": "Warning: Match Expression matches no targets." + }, "Dashboard": { "ADD_CARD_HELPER_TEXT": "Choose a card type to add to your Dashboard. Some cards require additional configuration.", "CARD_CATALOG_DESCRIPTION": "Cards added to this Dashboard Layout present information at a glance about the selected target. The layout is preserved for all targets viewed on this client.", @@ -271,6 +291,9 @@ }, "TITLE": "Upload Dashboard Layout Template" }, + "MATCH_EXPRESSION_VISUALIZER": { + "TITLE": "Match Expression visualizer" + }, "MeridiemPicker": { "ARIA_LABELS": { "LISTBOX": "Select AM or PM" @@ -286,6 +309,27 @@ "INVALID_UPLOADS_one": "The file does not contain valid Recording metadata:", "INVALID_UPLOADS_other": "These files do not contain valid Recording metadata:" }, + "RuleDeleteWarningModal": { + "CLEAN_DESCRIPTION": "Clean will stop any Active Recordings that {{ruleName}} created." + }, + "Rules": { + "ABOUT_BODY": "Automated Rules define a dynamic set of target JVMs to connect to and start <0>Active Recordings using a specific <1>Event Template when the Automated Rule is created and when any new matching target JVMs appear. If your Target JVM connections require JMX Credentials, you can configure these in <2>Security. Automated Rules can be configured to periodically copy the contents of the Active Recording to <3>Archives to ensure you always have up-to-date information about your JVMs.", + "ABOUT_TITLE": "About Automated Rules", + "ARCHIVAL_PERIOD_TOOLTIP": "Period in seconds. Cryostat will connect to matching targets at this interval and copy the relevant Recording data into its archives. Values less than 1 prevent data from being repeatedly copied into archives - Recordings will be started and remain only in Target JVM memory.", + "EVENT_SPECIFIER_TOOLTIP": "The name and location of the Event Template applied by this rule.", + "INITIAL_DELAY_TOOLTIP": "Initial delay in seconds. Cryostat will wait this amount of time before first copying Recording data into its archives. Values less than 0 default to equal to the Archival period. You can set a non-zero Initial delay with a zero Archival period, which will start a Recording and copy it into archives exactly once after a set delay.", + "MATCH_EXPRESSION_TOOLTIP": "A code-snippet expression which must evaluate to a boolean when applied to a given target. If the expression evaluates to true then the rule applies to that target.", + "MAX_AGE_TOOLTIP": "The maximum age in seconds for data kept in the JFR Recordings started by this rule. Values less than 1 indicate no limit.", + "MAX_SIZE_TOOLTIP": "The maximum size in bytes for JFR Recordings started by this rule. Values less than 1 indicate no limit.", + "PRESERVED_ARCHIVES_TOOLTIP": "The number of Recording copies to be maintained in the Cryostat archives. Cryostat will continue retrieving further archived copies and trimming the oldest copies from the archive to maintain this limit. Values less than 1 prevent data from being copied into archives - Recordings will be started and remain only in Target JVM memory." + }, + "RulesUploadModal": { + "DESCRIPTION": "Select an Automated Rules definition file to upload. File must be in valid JSON format.", + "HEADER_CONTENT": "Whats this?", + "INVALID_RULE_CONTENT": "Automated Rule content is invalid.", + "JSON_FILE": "JSON File", + "TITLE": "Upload Automated Rules" + }, "SETTINGS": { "AUTO_REFRESH": { "CHECKBOX_LABEL": "Enabled", diff --git a/src/app/Rules/CreateRule.tsx b/src/app/Rules/CreateRule.tsx index aa6c906a3..8408bdabd 100644 --- a/src/app/Rules/CreateRule.tsx +++ b/src/app/Rules/CreateRule.tsx @@ -56,6 +56,7 @@ import { import { HelpIcon } from '@patternfly/react-icons'; import _ from 'lodash'; import * as React from 'react'; +import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { combineLatest, forkJoin, iif, of, Subject } from 'rxjs'; import { catchError, debounceTime, map, switchMap, tap } from 'rxjs/operators'; @@ -68,6 +69,7 @@ export const CreateRuleForm: React.FC = (_props) => { const context = React.useContext(ServiceContext); const notifications = React.useContext(NotificationsContext); const navigate = useNavigate(); + const { t } = useTranslation(); // Do not use useSearchExpression for display. This causes the cursor to jump to the end due to async updates. const matchExprService = useMatchExpressionSvc(); const addSubscription = useSubscriptions(); @@ -346,22 +348,8 @@ export const CreateRuleForm: React.FC = (_props) => { return (
- - Automated Rules are configurations that instruct Cryostat to create JDK Flight Recordings on matching Target JVM - applications. Each Automated Rule specifies parameters for which Event Template to use, how much data should be - kept in the application Recording buffer, and how frequently Cryostat should copy the application Recording - buffer into Cryostat's own archived storage. - - - - - - {formData.nameValid === ValidatedOptions.error - ? 'A rule name can contain only letters, numbers, and underscores.' - : 'Enter a rule name.'} - - - + {t('CreateRule.ABOUT')} + = (_props) => { onChange={handleNameChange} validated={formData.nameValid} /> - - - - Enter a rule description. This is only used for display purposes to aid in identifying rules and their - intentions. + + {formData.nameValid === ValidatedOptions.error + ? t('CreateRule.NAME_HINT') + : t('CreateRule.NAME_HELPER_TEXT')} + +