fix grafana-sql package translations

This commit is contained in:
Ashley Harrison
2025-06-17 14:50:21 +01:00
parent b8a3814d52
commit 3a85160deb
21 changed files with 233 additions and 208 deletions
@@ -29,7 +29,7 @@ export function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }: ConfirmMod
<div className={styles.modalHeaderTitle}> <div className={styles.modalHeaderTitle}>
<Icon name="exclamation-triangle" size="lg" /> <Icon name="exclamation-triangle" size="lg" />
<span className={styles.titleText}> <span className={styles.titleText}>
<Trans i18nKey="components.confirm-modal.warning">Warning</Trans> <Trans i18nKey="grafana-sql.components.confirm-modal.warning">Warning</Trans>
</span> </span>
</div> </div>
} }
@@ -37,23 +37,25 @@ export function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }: ConfirmMod
isOpen={isOpen} isOpen={isOpen}
> >
<p> <p>
<Trans i18nKey="components.confirm-modal.builder-mode"> <Trans i18nKey="grafana-sql.components.confirm-modal.builder-mode">
Builder mode does not display changes made in code. The query builder will display the last changes you made Builder mode does not display changes made in code. The query builder will display the last changes you made
in builder mode. in builder mode.
</Trans> </Trans>
</p> </p>
<p> <p>
<Trans i18nKey="components.confirm-modal.clipboard">Do you want to copy your code to the clipboard?</Trans> <Trans i18nKey="grafana-sql.components.confirm-modal.clipboard">
Do you want to copy your code to the clipboard?
</Trans>
</p> </p>
<Modal.ButtonRow> <Modal.ButtonRow>
<Button type="button" variant="secondary" onClick={onCancel} fill="outline"> <Button type="button" variant="secondary" onClick={onCancel} fill="outline">
<Trans i18nKey="components.confirm-modal.cancel">Cancel</Trans> <Trans i18nKey="grafana-sql.components.confirm-modal.cancel">Cancel</Trans>
</Button> </Button>
<Button variant="destructive" type="button" onClick={onDiscard} ref={buttonRef}> <Button variant="destructive" type="button" onClick={onDiscard} ref={buttonRef}>
<Trans i18nKey="components.confirm-modal.discard-code-and-switch">Discard code and switch</Trans> <Trans i18nKey="grafana-sql.components.confirm-modal.discard-code-and-switch">Discard code and switch</Trans>
</Button> </Button>
<Button variant="primary" onClick={onCopy}> <Button variant="primary" onClick={onCopy}>
<Trans i18nKey="components.confirm-modal.copy-code-and-switch">Copy code and switch</Trans> <Trans i18nKey="grafana-sql.components.confirm-modal.copy-code-and-switch">Copy code and switch</Trans>
</Button> </Button>
</Modal.ButtonRow> </Modal.ButtonRow>
</Modal> </Modal>
@@ -76,7 +76,7 @@ export const DatasetSelector = ({
return ( return (
<Select <Select
aria-label={t('components.dataset-selector.aria-label-dataset-selector', 'Dataset selector')} aria-label={t('grafana-sql.querybuilder.dataset-selector.aria-label-dataset-selector', 'Dataset selector')}
inputId={inputId} inputId={inputId}
value={dataset} value={dataset}
options={state.value} options={state.value}
@@ -20,7 +20,7 @@ export class ErrorBoundary extends React.Component<React.PropsWithChildren<Props
if (this.state.hasError) { if (this.state.hasError) {
const FallBack = this.props.fallBackComponent || ( const FallBack = this.props.fallBackComponent || (
<div> <div>
<Trans i18nKey="components.error-boundary.fall-back.error">Error</Trans> <Trans i18nKey="grafana-sql.components.error-boundary.fall-back.error">Error</Trans>
</div> </div>
); );
return FallBack; return FallBack;
@@ -15,7 +15,7 @@ export function SqlQueryEditorLazy(props: SqlQueryEditorProps) {
<Suspense <Suspense
fallback={ fallback={
<LoadingPlaceholder <LoadingPlaceholder
text={t('components.sql-query-editor-lazy.text-loading-editor', 'Loading editor')} text={t('grafana-sql.querybuilder.sql-query-editor-lazy.text-loading-editor', 'Loading editor')}
className={styles.container} className={styles.container}
/> />
} }
@@ -127,9 +127,9 @@ export function QueryHeader({
<> <>
<EditorHeader> <EditorHeader>
<InlineSelect <InlineSelect
label={t('components.query-header.label-format', 'Format')} label={t('grafana-sql.querybuilder.query-header.label-format', 'Format')}
value={query.format} value={query.format}
placeholder={t('components.query-header.placeholder-select-format', 'Select format')} placeholder={t('grafana-sql.querybuilder.query-header.placeholder-select-format', 'Select format')}
menuShouldPortal menuShouldPortal
onChange={onFormatChange} onChange={onFormatChange}
options={QUERY_FORMAT_OPTIONS} options={QUERY_FORMAT_OPTIONS}
@@ -139,7 +139,7 @@ export function QueryHeader({
<> <>
<InlineSwitch <InlineSwitch
id={`sql-filter-${htmlId}`} id={`sql-filter-${htmlId}`}
label={t('components.query-header.label-filter', 'Filter')} label={t('grafana-sql.querybuilder.query-header.label-filter', 'Filter')}
data-testid={selectors.components.SQLQueryEditor.headerFilterSwitch} data-testid={selectors.components.SQLQueryEditor.headerFilterSwitch}
transparent={true} transparent={true}
showLabel={true} showLabel={true}
@@ -160,7 +160,7 @@ export function QueryHeader({
<InlineSwitch <InlineSwitch
id={`sql-group-${htmlId}`} id={`sql-group-${htmlId}`}
label={t('components.query-header.label-group', 'Group')} label={t('grafana-sql.querybuilder.query-header.label-group', 'Group')}
data-testid={selectors.components.SQLQueryEditor.headerGroupSwitch} data-testid={selectors.components.SQLQueryEditor.headerGroupSwitch}
transparent={true} transparent={true}
showLabel={true} showLabel={true}
@@ -181,7 +181,7 @@ export function QueryHeader({
<InlineSwitch <InlineSwitch
id={`sql-order-${htmlId}`} id={`sql-order-${htmlId}`}
label={t('components.query-header.label-order', 'Order')} label={t('grafana-sql.querybuilder.query-header.label-order', 'Order')}
data-testid={selectors.components.SQLQueryEditor.headerOrderSwitch} data-testid={selectors.components.SQLQueryEditor.headerOrderSwitch}
transparent={true} transparent={true}
showLabel={true} showLabel={true}
@@ -202,7 +202,7 @@ export function QueryHeader({
<InlineSwitch <InlineSwitch
id={`sql-preview-${htmlId}`} id={`sql-preview-${htmlId}`}
label={t('components.query-header.label-preview', 'Preview')} label={t('grafana-sql.querybuilder.query-header.label-preview', 'Preview')}
data-testid={selectors.components.SQLQueryEditor.headerPreviewSwitch} data-testid={selectors.components.SQLQueryEditor.headerPreviewSwitch}
transparent={true} transparent={true}
showLabel={true} showLabel={true}
@@ -227,13 +227,13 @@ export function QueryHeader({
{isQueryRunnable ? ( {isQueryRunnable ? (
<Button icon="play" variant="primary" size="sm" onClick={() => onRunQuery()}> <Button icon="play" variant="primary" size="sm" onClick={() => onRunQuery()}>
<Trans i18nKey="components.query-header.run-query">Run query</Trans> <Trans i18nKey="grafana-sql.components.query-header.run-query">Run query</Trans>
</Button> </Button>
) : ( ) : (
<Tooltip <Tooltip
theme="error" theme="error"
content={ content={
<Trans i18nKey="components.query-header.content-invalid-query"> <Trans i18nKey="grafana-sql.components.query-header.content-invalid-query">
Your query is invalid. Check below for details. <br /> Your query is invalid. Check below for details. <br />
However, you can still run this query. However, you can still run this query.
</Trans> </Trans>
@@ -241,7 +241,7 @@ export function QueryHeader({
placement="top" placement="top"
> >
<Button icon="exclamation-triangle" variant="secondary" size="sm" onClick={() => onRunQuery()}> <Button icon="exclamation-triangle" variant="secondary" size="sm" onClick={() => onRunQuery()}>
<Trans i18nKey="components.query-header.run-query">Run query</Trans> <Trans i18nKey="grafana-sql.components.query-header.run-query">Run query</Trans>
</Button> </Button>
</Tooltip> </Tooltip>
)} )}
@@ -296,7 +296,7 @@ export function QueryHeader({
<Space v={0.5} /> <Space v={0.5} />
<EditorRow> <EditorRow>
{datasetDropdownIsAvailable() && ( {datasetDropdownIsAvailable() && (
<EditorField label={t('components.query-header.label-dataset', 'Dataset')} width={25}> <EditorField label={t('grafana-sql.querybuilder.query-header.label-dataset', 'Dataset')} width={25}>
<DatasetSelector <DatasetSelector
db={db} db={db}
inputId={`sql-dataset-${htmlId}`} inputId={`sql-dataset-${htmlId}`}
@@ -307,7 +307,7 @@ export function QueryHeader({
/> />
</EditorField> </EditorField>
)} )}
<EditorField label={t('components.query-header.label-table', 'Table')} width={25}> <EditorField label={t('grafana-sql.querybuilder.query-header.label-table', 'Table')} width={25}>
<TableSelector <TableSelector
db={db} db={db}
inputId={`sql-tableselect-${htmlId}`} inputId={`sql-tableselect-${htmlId}`}
@@ -30,7 +30,7 @@ export const TableSelector = ({ db, dataset, table, className, onChange, inputId
<Select <Select
className={className} className={className}
disabled={state.loading} disabled={state.loading}
aria-label={t('components.table-selector.aria-label-table-selector', 'Table selector')} aria-label={t('grafana-sql.querybuilder.table-selector.aria-label-table-selector', 'Table selector')}
inputId={inputId} inputId={inputId}
data-testid={selectors.components.SQLQueryEditor.headerTableSelector} data-testid={selectors.components.SQLQueryEditor.headerTableSelector}
value={table} value={table}
@@ -40,8 +40,8 @@ export const TableSelector = ({ db, dataset, table, className, onChange, inputId
menuShouldPortal={true} menuShouldPortal={true}
placeholder={ placeholder={
state.loading state.loading
? t('components.table-selector.placeholder-loading', 'Loading tables') ? t('grafana-sql.querybuilder.table-selector.placeholder-loading', 'Loading tables')
: t('components.table-selector.placeholder-select-table', 'Select table') : t('grafana-sql.querybuilder.table-selector.placeholder-select-table', 'Select table')
} }
allowCustomValue={true} allowCustomValue={true}
/> />
@@ -84,18 +84,20 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
const labelWidth = 40; const labelWidth = 40;
return ( return (
<ConfigSubSection title={t('components.connection-limits.title-connection-limits', 'Connection limits')}> <ConfigSubSection
title={t('grafana-sql.querybuilder.connection-limits.title-connection-limits', 'Connection limits')}
>
<Field <Field
label={ label={
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.connection-limits.max-open">Max open</Trans> <Trans i18nKey="grafana-sql.components.connection-limits.max-open">Max open</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.connection-limits.content-max-open"> <Trans i18nKey="grafana-sql.components.connection-limits.content-max-open">
The maximum number of open connections to the database. If <i>Max idle connections</i> is greater The maximum number of open connections to the database. If <i>Max idle connections</i> is greater
than 0 and the <i>Max open connections</i> is less than <i>Max idle connections</i>, then than 0 and the <i>Max open connections</i> is less than <i>Max idle connections</i>, then
<i>Max idle connections</i> will be reduced to match the <i>Max open connections</i> limit. If set <i>Max idle connections</i> will be reduced to match the <i>Max open connections</i> limit. If set
@@ -125,13 +127,13 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.connection-limits.auto-max-idle">Auto max idle</Trans> <Trans i18nKey="grafana-sql.components.connection-limits.auto-max-idle">Auto max idle</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans <Trans
i18nKey="components.connection-limits.content-auto-max-idle" i18nKey="grafana-sql.components.connection-limits.content-auto-max-idle"
values={{ defaultMaxIdle: config.sqlConnectionLimits.maxIdleConns }} values={{ defaultMaxIdle: config.sqlConnectionLimits.maxIdleConns }}
> >
If enabled, automatically set the number of <i>Maximum idle connections</i> to the same value as If enabled, automatically set the number of <i>Maximum idle connections</i> to the same value as
@@ -155,12 +157,12 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.connection-limits.max-idle">Max idle</Trans> <Trans i18nKey="grafana-sql.components.connection-limits.max-idle">Max idle</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.connection-limits.content-max-idle"> <Trans i18nKey="grafana-sql.components.connection-limits.content-max-idle">
The maximum number of connections in the idle connection pool.If <i>Max open connections</i> is The maximum number of connections in the idle connection pool.If <i>Max open connections</i> is
greater than 0 but less than the <i>Max idle connections</i>, then the <i>Max idle connections</i>{' '} greater than 0 but less than the <i>Max idle connections</i>, then the <i>Max idle connections</i>{' '}
will be reduced to match the <i>Max open connections</i> limit. If set to 0, no idle connections will be reduced to match the <i>Max open connections</i> limit. If set to 0, no idle connections
@@ -194,12 +196,12 @@ export const ConnectionLimits = <T extends SQLConnectionLimits>(props: Props<T>)
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.connection-limits.max-lifetime">Max lifetime</Trans> <Trans i18nKey="grafana-sql.components.connection-limits.max-lifetime">Max lifetime</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.connection-limits.content-max-lifetime"> <Trans i18nKey="grafana-sql.components.connection-limits.content-max-lifetime">
The maximum amount of time in seconds a connection may be reused. If set to 0, connections are The maximum amount of time in seconds a connection may be reused. If set to 0, connections are
reused forever. reused forever.
</Trans> </Trans>
@@ -27,14 +27,14 @@ export const TLSSecretsConfig = <T extends DataSourceJsonData, S extends {} = {}
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.tlssecrets-config.tlsssl-client-certificate"> <Trans i18nKey="grafana-sql.components.tlssecrets-config.tlsssl-client-certificate">
TLS/SSL Client Certificate TLS/SSL Client Certificate
</Trans> </Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.tlssecrets-config.content-tlsssl-client-certificate"> <Trans i18nKey="grafana-sql.components.tlssecrets-config.content-tlsssl-client-certificate">
To authenticate with an TLS/SSL client certificate, provide the client certificate here. To authenticate with an TLS/SSL client certificate, provide the client certificate here.
</Trans> </Trans>
</span> </span>
@@ -65,12 +65,14 @@ export const TLSSecretsConfig = <T extends DataSourceJsonData, S extends {} = {}
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.tlssecrets-config.tlsssl-root-certificate">TLS/SSL Root Certificate</Trans> <Trans i18nKey="grafana-sql.components.tlssecrets-config.tlsssl-root-certificate">
TLS/SSL Root Certificate
</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.tlssecrets-config.content-tlsssl-root-certificate"> <Trans i18nKey="grafana-sql.components.tlssecrets-config.content-tlsssl-root-certificate">
If the selected TLS/SSL mode requires a server root certificate, provide it here If the selected TLS/SSL mode requires a server root certificate, provide it here
</Trans> </Trans>
</span> </span>
@@ -101,12 +103,12 @@ export const TLSSecretsConfig = <T extends DataSourceJsonData, S extends {} = {}
<Label> <Label>
<Stack gap={0.5}> <Stack gap={0.5}>
<span> <span>
<Trans i18nKey="components.tlssecrets-config.tlsssl-client-key">TLS/SSL Client Key</Trans> <Trans i18nKey="grafana-sql.components.tlssecrets-config.tlsssl-client-key">TLS/SSL Client Key</Trans>
</span> </span>
<Tooltip <Tooltip
content={ content={
<span> <span>
<Trans i18nKey="components.tlssecrets-config.content-tlsssl-client-key"> <Trans i18nKey="grafana-sql.components.tlssecrets-config.content-tlsssl-client-key">
To authenticate with a client TLS/SSL certificate, provide the key here. To authenticate with a client TLS/SSL certificate, provide the key here.
</Trans> </Trans>
</span> </span>
@@ -81,7 +81,7 @@ export function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ..
}} }}
name="brackets-curly" name="brackets-curly"
size="xs" size="xs"
tooltip={t('components.query-toolbox.tooltip-format-query', 'Format query')} tooltip={t('grafana-sql.querybuilder.query-toolbox.tooltip-format-query', 'Format query')}
/> />
)} )}
{onExpand && ( {onExpand && (
@@ -98,14 +98,14 @@ export function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ..
size="xs" size="xs"
tooltip={ tooltip={
isExpanded isExpanded
? t('components.query-toolbox.tooltip-collapse', 'Collapse editor') ? t('grafana-sql.querybuilder.query-toolbox.tooltip-collapse', 'Collapse editor')
: t('components.query-toolbox.tooltip-expand', 'Expand editor') : t('grafana-sql.querybuilder.query-toolbox.tooltip-expand', 'Expand editor')
} }
/> />
)} )}
<Tooltip <Tooltip
content={t( content={t(
'components.query-toolbox.content-hit-ctrlcmdreturn-to-run-query', 'grafana-sql.querybuilder.query-toolbox.content-hit-ctrlcmdreturn-to-run-query',
'Hit CTRL/CMD+Return to run query' 'Hit CTRL/CMD+Return to run query'
)} )}
> >
@@ -80,7 +80,7 @@ export function QueryValidator({ db, query, onValidate, range }: QueryValidatorP
{state.loading && ( {state.loading && (
<div className={styles.info}> <div className={styles.info}>
<Spinner inline={true} size="xs" />{' '} <Spinner inline={true} size="xs" />{' '}
<Trans i18nKey="components.query-validator.validating-query">Validating query...</Trans> <Trans i18nKey="grafana-sql.components.query-validator.validating-query">Validating query...</Trans>
</div> </div>
)} )}
{!state.loading && state.value && ( {!state.loading && state.value && (
@@ -89,7 +89,7 @@ export function QueryValidator({ db, query, onValidate, range }: QueryValidatorP
{state.value.isValid && state.value.statistics && ( {state.value.isValid && state.value.statistics && (
<div className={styles.valid}> <div className={styles.valid}>
<Trans <Trans
i18nKey="components.query-validator.query-will-process" i18nKey="grafana-sql.components.query-validator.query-will-process"
values={{ bytes: formattedValueToString(valueFormatter(state.value.statistics.TotalBytesProcessed)) }} values={{ bytes: formattedValueToString(valueFormatter(state.value.statistics.TotalBytesProcessed)) }}
> >
<Icon name="check" /> This query will process <strong>{'{{bytes}}'}</strong> when run. <Icon name="check" /> This query will process <strong>{'{{bytes}}'}</strong> when run.
@@ -82,7 +82,7 @@ export function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryTo
justifyContent: 'center', justifyContent: 'center',
}} }}
> >
<Trans i18nKey="components.raw-editor.render-placeholder.editing-in-expanded-code-editor"> <Trans i18nKey="grafana-sql.components.raw-editor.render-placeholder.editing-in-expanded-code-editor">
Editing in expanded code editor Editing in expanded code editor
</Trans> </Trans>
</div> </div>
@@ -94,7 +94,9 @@ export function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryTo
{isExpanded ? renderPlaceholder() : renderEditor()} {isExpanded ? renderPlaceholder() : renderEditor()}
{isExpanded && ( {isExpanded && (
<Modal <Modal
title={t('components.raw-editor.title-query-num', 'Query {{queryNum}}', { queryNum: query.refId })} title={t('grafana-sql.querybuilder.raw-editor.title-query-num', 'Query {{queryNum}}', {
queryNum: query.refId,
})}
closeOnBackdropClick={false} closeOnBackdropClick={false}
closeOnEscape={false} closeOnEscape={false}
className={styles.modal} className={styles.modal}
@@ -69,7 +69,7 @@ export const widgets: Widgets = {
return ( return (
<Select <Select
id={props.id} id={props.id}
aria-label={t('components.widgets.aria-label-macros-value-selector', 'Macros value selector')} aria-label={t('grafana-sql.querybuilder.widgets.aria-label-macros-value-selector', 'Macros value selector')}
menuShouldPortal menuShouldPortal
options={macros.map(toOption)} options={macros.map(toOption)}
value={props?.value} value={props?.value}
@@ -125,7 +125,7 @@ export const settings: Settings = {
return ( return (
<Select <Select
id={conjProps?.id} id={conjProps?.id}
aria-label={t('components.settings.aria-label-conjunction', 'Conjunction')} aria-label={t('grafana-sql.querybuilder.settings.aria-label-conjunction', 'Conjunction')}
data-testid={selectors.components.SQLQueryEditor.filterConjunction} data-testid={selectors.components.SQLQueryEditor.filterConjunction}
menuShouldPortal menuShouldPortal
options={conjProps?.conjunctionOptions ? Object.keys(conjProps?.conjunctionOptions).map(toOption) : undefined} options={conjProps?.conjunctionOptions ? Object.keys(conjProps?.conjunctionOptions).map(toOption) : undefined}
@@ -141,7 +141,7 @@ export const settings: Settings = {
<Select <Select
id={fieldProps?.id} id={fieldProps?.id}
width={25} width={25}
aria-label={t('components.settings.aria-label-field', 'Field')} aria-label={t('grafana-sql.querybuilder.settings.aria-label-field', 'Field')}
data-testid={selectors.components.SQLQueryEditor.filterField} data-testid={selectors.components.SQLQueryEditor.filterField}
menuShouldPortal menuShouldPortal
options={fieldProps?.items.map((f) => { options={fieldProps?.items.map((f) => {
@@ -165,7 +165,7 @@ export const settings: Settings = {
return ( return (
<Button <Button
type="button" type="button"
title={t('components.settings.title-button-filter', '{{ buttonLabel }} filter', { title={t('grafana-sql.querybuilder.settings.title-button-filter', '{{ buttonLabel }} filter', {
buttonLabel: buttonProps?.label, buttonLabel: buttonProps?.label,
})} })}
onClick={buttonProps?.onClick} onClick={buttonProps?.onClick}
@@ -180,7 +180,7 @@ export const settings: Settings = {
return ( return (
<Select <Select
options={operatorProps?.items.map((op) => ({ label: op.label, value: op.key }))} options={operatorProps?.items.map((op) => ({ label: op.label, value: op.key }))}
aria-label={t('components.settings.aria-label-operator', 'Operator')} aria-label={t('grafana-sql.querybuilder.settings.aria-label-operator', 'Operator')}
data-testid={selectors.components.SQLQueryEditor.filterOperator} data-testid={selectors.components.SQLQueryEditor.filterOperator}
menuShouldPortal menuShouldPortal
value={operatorProps?.selectedKey} value={operatorProps?.selectedKey}
@@ -304,7 +304,7 @@ function getCustomOperators(config: BasicConfig) {
sqlFormatOp: customSqlNotInFormatter, sqlFormatOp: customSqlNotInFormatter,
}, },
[Op.MACROS]: { [Op.MACROS]: {
label: t('components.get-custom-operators.custom-operators.label.macros', 'Macros'), label: t('grafana-sql.querybuilder.get-custom-operators.custom-operators.label.macros', 'Macros'),
sqlFormatOp: (field: string, _operator: string, value: string | string[] | ImmutableList<string>) => { sqlFormatOp: (field: string, _operator: string, value: string | string[] | ImmutableList<string>) => {
if (value === TIME_FILTER) { if (value === TIME_FILTER) {
return `$__timeFilter(${field})`; return `$__timeFilter(${field})`;
@@ -47,14 +47,14 @@ function makeRenderColumn({ options }: { options?: Array<SelectableValue<string>
<InputGroup> <InputGroup>
<Select <Select
value={item.property?.name ? toOption(item.property.name) : null} value={item.property?.name ? toOption(item.property.name) : null}
aria-label={t('components.make-render-column.render-column.aria-label-group-by', 'Group by')} aria-label={t('grafana-sql.querybuilder.make-render-column.render-column.aria-label-group-by', 'Group by')}
options={options} options={options}
menuShouldPortal menuShouldPortal
onChange={({ value }) => value && onChangeItem(setGroupByField(value))} onChange={({ value }) => value && onChangeItem(setGroupByField(value))}
/> />
<AccessoryButton <AccessoryButton
title={t( title={t(
'components.make-render-column.render-column.title-remove-group-by-column', 'grafana-sql.querybuilder.make-render-column.render-column.title-remove-group-by-column',
'Remove group by column' 'Remove group by column'
)} )}
icon="times" icon="times"
@@ -60,10 +60,10 @@ export function OrderByRow({ sql, onSqlChange, columns, showOffset }: OrderByRow
return ( return (
<> <>
<EditorField label={t('components.order-by-row.label-order-by', 'Order by')} width={25}> <EditorField label={t('grafana-sql.querybuilder.order-by-row.label-order-by', 'Order by')} width={25}>
<InputGroup> <InputGroup>
<Select <Select
aria-label={t('components.order-by-row.aria-label-order-by', 'Order by')} aria-label={t('grafana-sql.querybuilder.order-by-row.aria-label-order-by', 'Order by')}
options={columns} options={columns}
value={sql.orderBy?.property.name ? toOption(sql.orderBy.property.name) : null} value={sql.orderBy?.property.name ? toOption(sql.orderBy.property.name) : null}
isClearable isClearable
@@ -81,11 +81,11 @@ export function OrderByRow({ sql, onSqlChange, columns, showOffset }: OrderByRow
/> />
</InputGroup> </InputGroup>
</EditorField> </EditorField>
<EditorField label={t('components.order-by-row.label-limit', 'Limit')} optional width={25}> <EditorField label={t('grafana-sql.querybuilder.order-by-row.label-limit', 'Limit')} optional width={25}>
<Input type="number" min={0} id={uniqueId('limit-')} value={sql.limit || ''} onChange={onLimitChange} /> <Input type="number" min={0} id={uniqueId('limit-')} value={sql.limit || ''} onChange={onLimitChange} />
</EditorField> </EditorField>
{showOffset && ( {showOffset && (
<EditorField label={t('components.order-by-row.label-offset', 'Offset')} optional width={25}> <EditorField label={t('grafana-sql.querybuilder.order-by-row.label-offset', 'Offset')} optional width={25}>
<Input type="number" id={uniqueId('offset-')} value={sql.offset || ''} onChange={onOffsetChange} /> <Input type="number" id={uniqueId('offset-')} value={sql.offset || ''} onChange={onOffsetChange} />
</EditorField> </EditorField>
)} )}
@@ -28,10 +28,10 @@ export function Preview({ rawSql, datasourceType }: PreviewProps) {
const labelElement = ( const labelElement = (
<div className={styles.labelWrapper}> <div className={styles.labelWrapper}>
<span className={styles.label}> <span className={styles.label}>
<Trans i18nKey="components.preview.label-element.preview">Preview</Trans> <Trans i18nKey="grafana-sql.components.preview.label-element.preview">Preview</Trans>
</span> </span>
<IconButton <IconButton
tooltip={t('components.preview.label-element.tooltip-copy-to-clipboard', 'Copy to clipboard')} tooltip={t('grafana-sql.querybuilder.preview.label-element.tooltip-copy-to-clipboard', 'Copy to clipboard')}
onClick={() => copyPreview(rawSql)} onClick={() => copyPreview(rawSql)}
name="copy" name="copy"
/> />
@@ -16,7 +16,7 @@ export function SelectColumn({ columns, onParameterChange, value }: Props) {
const selectInputId = useId(); const selectInputId = useId();
return ( return (
<EditorField label={t('components.select-column.label-column', 'Column')} width={25}> <EditorField label={t('grafana-sql.querybuilder.select-column.label-column', 'Column')} width={25}>
<Select <Select
value={value} value={value}
data-testid={selectors.components.SQLQueryEditor.selectColumn} data-testid={selectors.components.SQLQueryEditor.selectColumn}
@@ -87,7 +87,7 @@ export function SelectCustomFunctionParameters({
onChange={(e) => onParameterChange(index)(e.currentTarget.value)} onChange={(e) => onParameterChange(index)(e.currentTarget.value)}
value={param.name} value={param.name}
aria-label={t( aria-label={t(
'components.select-custom-function-parameters.aria-label-parameter', 'grafana-sql.querybuilder.select-custom-function-parameters.aria-label-parameter',
'Parameter {{index}} for column {{columnIndex}}', 'Parameter {{index}} for column {{columnIndex}}',
{ index, columnIndex } { index, columnIndex }
)} )}
@@ -95,7 +95,7 @@ export function SelectCustomFunctionParameters({
addonAfter={ addonAfter={
<Button <Button
title={t( title={t(
'components.select-custom-function-parameters.render-parameters.params.title-remove-parameter', 'grafana-sql.querybuilder.select-custom-function-parameters.render-parameters.params.title-remove-parameter',
'Remove parameter' 'Remove parameter'
)} )}
type="button" type="button"
@@ -127,7 +127,7 @@ export function SelectCustomFunctionParameters({
variant="secondary" variant="secondary"
size="md" size="md"
icon="plus" icon="plus"
title={t('components.select-custom-function-parameters.title-add-parameter', 'Add parameter')} title={t('grafana-sql.querybuilder.select-custom-function-parameters.title-add-parameter', 'Add parameter')}
/> />
<InlineLabel className={styles.label}>)</InlineLabel> <InlineLabel className={styles.label}>)</InlineLabel>
</> </>
@@ -30,8 +30,8 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
// Add necessary alias options for time series format // Add necessary alias options for time series format
// when that format has been selected // when that format has been selected
if (query.format === QueryFormat.Timeseries) { if (query.format === QueryFormat.Timeseries) {
timeSeriesAliasOpts.push({ label: t('components.select-row.label.time', 'time'), value: 'time' }); timeSeriesAliasOpts.push({ label: t('grafana-sql.querybuilder.select-row.label.time', 'time'), value: 'time' });
timeSeriesAliasOpts.push({ label: t('components.select-row.label.value', 'value'), value: 'value' }); timeSeriesAliasOpts.push({ label: t('grafana-sql.querybuilder.select-row.label.value', 'value'), value: 'value' });
} }
const onAggregationChange = useCallback( const onAggregationChange = useCallback(
@@ -93,8 +93,11 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
const aggregateOptions = () => { const aggregateOptions = () => {
const options: Array<SelectableValue<string>> = [ const options: Array<SelectableValue<string>> = [
{ label: t('components.select-row.aggregate-options.options.label.aggregations', 'Aggregations'), options: [] }, {
{ label: t('components.select-row.aggregate-options.options.label.macros', 'Macros'), options: [] }, label: t('grafana-sql.querybuilder.select-row.aggregate-options.options.label.aggregations', 'Aggregations'),
options: [],
},
{ label: t('grafana-sql.querybuilder.select-row.aggregate-options.options.label.macros', 'Macros'), options: [] },
]; ];
for (const func of db.functions()) { for (const func of db.functions()) {
// Create groups for macros // Create groups for macros
@@ -113,7 +116,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
<div key={index}> <div key={index}>
<Stack gap={2} alignItems="end"> <Stack gap={2} alignItems="end">
<EditorField <EditorField
label={t('components.select-row.label-data-operations', 'Data operations')} label={t('grafana-sql.querybuilder.select-row.label-data-operations', 'Data operations')}
optional optional
width={25} width={25}
> >
@@ -137,7 +140,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
db={db} db={db}
/> />
<EditorField label={t('components.select-row.label-alias', 'Alias')} optional width={15}> <EditorField label={t('grafana-sql.querybuilder.select-row.label-alias', 'Alias')} optional width={15}>
<Select <Select
value={item.alias ? toOption(item.alias) : null} value={item.alias ? toOption(item.alias) : null}
inputId={`select-alias-${index}-${uniqueId()}`} inputId={`select-alias-${index}-${uniqueId()}`}
@@ -150,7 +153,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
/> />
</EditorField> </EditorField>
<Button <Button
title={t('components.select-row.title-remove-column', 'Remove column')} title={t('grafana-sql.querybuilder.select-row.title-remove-column', 'Remove column')}
type="button" type="button"
icon="trash-alt" icon="trash-alt"
variant="secondary" variant="secondary"
@@ -164,7 +167,7 @@ export function SelectRow({ query, onQueryChange, db, columns }: SelectRowProps)
type="button" type="button"
onClick={addColumn} onClick={addColumn}
variant="secondary" variant="secondary"
title={t('components.select-row.title-add-column', 'Add column')} title={t('grafana-sql.querybuilder.select-row.title-add-column', 'Add column')}
size="md" size="md"
icon="plus" icon="plus"
className={styles.addButton} className={styles.addButton}
@@ -33,7 +33,7 @@ export const VisualEditor = ({ query, db, queryRowFilter, onChange, onValidate,
{queryRowFilter.filter && ( {queryRowFilter.filter && (
<EditorRow> <EditorRow>
<EditorField <EditorField
label={t('components.visual-editor.label-filter-by-column-value', 'Filter by column value')} label={t('grafana-sql.querybuilder.visual-editor.label-filter-by-column-value', 'Filter by column value')}
optional optional
> >
<SQLWhereRow fields={state.value || []} query={query} onQueryChange={onChange} db={db} /> <SQLWhereRow fields={state.value || []} query={query} onQueryChange={onChange} db={db} />
@@ -42,7 +42,7 @@ export const VisualEditor = ({ query, db, queryRowFilter, onChange, onValidate,
)} )}
{queryRowFilter.group && ( {queryRowFilter.group && (
<EditorRow> <EditorRow>
<EditorField label={t('components.visual-editor.label-group-by-column', 'Group by column')}> <EditorField label={t('grafana-sql.querybuilder.visual-editor.label-group-by-column', 'Group by column')}>
<SQLGroupByRow fields={state.value || []} query={query} onQueryChange={onChange} db={db} /> <SQLGroupByRow fields={state.value || []} query={query} onQueryChange={onChange} db={db} />
</EditorField> </EditorField>
</EditorRow> </EditorRow>
@@ -1,148 +1,162 @@
{ {
"components": { "grafana-sql": {
"confirm-modal": { "components": {
"builder-mode": "Builder mode does not display changes made in code. The query builder will display the last changes you made in builder mode.", "confirm-modal": {
"cancel": "Cancel", "builder-mode": "Builder mode does not display changes made in code. The query builder will display the last changes you made in builder mode.",
"clipboard": "Do you want to copy your code to the clipboard?", "cancel": "Cancel",
"copy-code-and-switch": "Copy code and switch", "clipboard": "Do you want to copy your code to the clipboard?",
"discard-code-and-switch": "Discard code and switch", "copy-code-and-switch": "Copy code and switch",
"warning": "Warning" "discard-code-and-switch": "Discard code and switch",
}, "warning": "Warning"
"connection-limits": {
"auto-max-idle": "Auto max idle",
"content-auto-max-idle": "If enabled, automatically set the number of <1>Maximum idle connections</1> to the same value as<3> Max open connections</3>. If the number of maximum open connections is not set it will be set to the default ({{defaultMaxIdle}}).",
"content-max-idle": "The maximum number of connections in the idle connection pool.If <1>Max open connections</1> is greater than 0 but less than the <3>Max idle connections</3>, then the <5>Max idle connections</5> will be reduced to match the <8>Max open connections</8> limit. If set to 0, no idle connections are retained.",
"content-max-lifetime": "The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever.",
"content-max-open": "The maximum number of open connections to the database. If <1>Max idle connections</1> is greater than 0 and the <3>Max open connections</3> is less than <5>Max idle connections</5>, then<7>Max idle connections</7> will be reduced to match the <9>Max open connections</9> limit. If set to 0, there is no limit on the number of open connections.",
"max-idle": "Max idle",
"max-lifetime": "Max lifetime",
"max-open": "Max open",
"title-connection-limits": "Connection limits"
},
"dataset-selector": {
"aria-label-dataset-selector": "Dataset selector"
},
"error-boundary": {
"fall-back": {
"error": "Error"
}
},
"get-custom-operators": {
"custom-operators": {
"label": {
"macros": "Macros"
}
}
},
"make-render-column": {
"render-column": {
"aria-label-group-by": "Group by",
"title-remove-group-by-column": "Remove group by column"
}
},
"order-by-row": {
"aria-label-order-by": "Order by",
"label-limit": "Limit",
"label-offset": "Offset",
"label-order-by": "Order by"
},
"preview": {
"label-element": {
"preview": "Preview",
"tooltip-copy-to-clipboard": "Copy to clipboard"
}
},
"query-header": {
"content-invalid-query": "Your query is invalid. Check below for details. <1></1>However, you can still run this query.",
"label-dataset": "Dataset",
"label-filter": "Filter",
"label-format": "Format",
"label-group": "Group",
"label-order": "Order",
"label-preview": "Preview",
"label-table": "Table",
"placeholder-select-format": "Select format",
"run-query": "Run query"
},
"query-toolbox": {
"content-hit-ctrlcmdreturn-to-run-query": "Hit CTRL/CMD+Return to run query",
"tooltip-collapse": "Collapse editor",
"tooltip-expand": "Expand editor",
"tooltip-format-query": "Format query"
},
"query-validator": {
"query-will-process": "<0></0> This query will process <2>{{bytes}}</2> when run.",
"validating-query": "Validating query..."
},
"raw-editor": {
"render-placeholder": {
"editing-in-expanded-code-editor": "Editing in expanded code editor"
}, },
"title-query-num": "Query {{queryNum}}" "connection-limits": {
}, "auto-max-idle": "Auto max idle",
"select-column": { "content-auto-max-idle": "If enabled, automatically set the number of <1>Maximum idle connections</1> to the same value as<3> Max open connections</3>. If the number of maximum open connections is not set it will be set to the default ({{defaultMaxIdle}}).",
"label-column": "Column" "content-max-idle": "The maximum number of connections in the idle connection pool.If <1>Max open connections</1> is greater than 0 but less than the <3>Max idle connections</3>, then the <5>Max idle connections</5> will be reduced to match the <8>Max open connections</8> limit. If set to 0, no idle connections are retained.",
}, "content-max-lifetime": "The maximum amount of time in seconds a connection may be reused. If set to 0, connections are reused forever.",
"select-custom-function-parameters": { "content-max-open": "The maximum number of open connections to the database. If <1>Max idle connections</1> is greater than 0 and the <3>Max open connections</3> is less than <5>Max idle connections</5>, then<7>Max idle connections</7> will be reduced to match the <9>Max open connections</9> limit. If set to 0, there is no limit on the number of open connections.",
"aria-label-parameter": "Parameter {{index}} for column {{columnIndex}}", "max-idle": "Max idle",
"render-parameters": { "max-lifetime": "Max lifetime",
"params": { "max-open": "Max open"
"title-remove-parameter": "Remove parameter" },
"error-boundary": {
"fall-back": {
"error": "Error"
} }
}, },
"title-add-parameter": "Add parameter" "preview": {
"label-element": {
"preview": "Preview"
}
},
"query-header": {
"content-invalid-query": "Your query is invalid. Check below for details. <1></1>However, you can still run this query.",
"run-query": "Run query"
},
"query-validator": {
"query-will-process": "<0></0> This query will process <2>{{bytes}}</2> when run.",
"validating-query": "Validating query..."
},
"raw-editor": {
"render-placeholder": {
"editing-in-expanded-code-editor": "Editing in expanded code editor"
}
},
"tlssecrets-config": {
"content-tlsssl-client-certificate": "To authenticate with an TLS/SSL client certificate, provide the client certificate here.",
"content-tlsssl-client-key": "To authenticate with a client TLS/SSL certificate, provide the key here.",
"content-tlsssl-root-certificate": "If the selected TLS/SSL mode requires a server root certificate, provide it here",
"tlsssl-client-certificate": "TLS/SSL Client Certificate",
"tlsssl-client-key": "TLS/SSL Client Key",
"tlsssl-root-certificate": "TLS/SSL Root Certificate"
}
}, },
"select-row": { "querybuilder": {
"aggregate-options": { "connection-limits": {
"options": { "title-connection-limits": "Connection limits"
},
"dataset-selector": {
"aria-label-dataset-selector": "Dataset selector"
},
"get-custom-operators": {
"custom-operators": {
"label": { "label": {
"aggregations": "Aggregations",
"macros": "Macros" "macros": "Macros"
} }
} }
}, },
"label": { "make-render-column": {
"time": "time", "render-column": {
"value": "value" "aria-label-group-by": "Group by",
"title-remove-group-by-column": "Remove group by column"
}
}, },
"label-alias": "Alias", "order-by-row": {
"label-data-operations": "Data operations", "aria-label-order-by": "Order by",
"title-add-column": "Add column", "label-limit": "Limit",
"title-remove-column": "Remove column" "label-offset": "Offset",
"label-order-by": "Order by"
},
"preview": {
"label-element": {
"tooltip-copy-to-clipboard": "Copy to clipboard"
}
},
"query-header": {
"label-dataset": "Dataset",
"label-filter": "Filter",
"label-format": "Format",
"label-group": "Group",
"label-order": "Order",
"label-preview": "Preview",
"label-table": "Table",
"placeholder-select-format": "Select format"
},
"query-toolbox": {
"content-hit-ctrlcmdreturn-to-run-query": "Hit CTRL/CMD+Return to run query",
"tooltip-collapse": "Collapse editor",
"tooltip-expand": "Expand editor",
"tooltip-format-query": "Format query"
},
"raw-editor": {
"title-query-num": "Query {{queryNum}}"
},
"select-column": {
"label-column": "Column"
},
"select-custom-function-parameters": {
"aria-label-parameter": "Parameter {{index}} for column {{columnIndex}}",
"render-parameters": {
"params": {
"title-remove-parameter": "Remove parameter"
}
},
"title-add-parameter": "Add parameter"
},
"select-row": {
"aggregate-options": {
"options": {
"label": {
"aggregations": "Aggregations",
"macros": "Macros"
}
}
},
"label": {
"time": "time",
"value": "value"
},
"label-alias": "Alias",
"label-data-operations": "Data operations",
"title-add-column": "Add column",
"title-remove-column": "Remove column"
},
"settings": {
"aria-label-conjunction": "Conjunction",
"aria-label-field": "Field",
"aria-label-operator": "Operator",
"title-button-filter": "{{ buttonLabel }} filter"
},
"sql-query-editor-lazy": {
"text-loading-editor": "Loading editor"
},
"table-selector": {
"aria-label-table-selector": "Table selector",
"placeholder-loading": "Loading tables",
"placeholder-select-table": "Select table"
},
"visual-editor": {
"label-filter-by-column-value": "Filter by column value",
"label-group-by-column": "Group by column"
},
"widgets": {
"aria-label-macros-value-selector": "Macros value selector"
}
}, },
"settings": { "utils": {
"aria-label-conjunction": "Conjunction", "get-columns-width-indices": {
"aria-label-field": "Field", "label-selected-columns": "Selected columns"
"aria-label-operator": "Operator", }
"title-button-filter": "{{ buttonLabel }} filter"
},
"sql-query-editor-lazy": {
"text-loading-editor": "Loading editor"
},
"table-selector": {
"aria-label-table-selector": "Table selector",
"placeholder-loading": "Loading tables",
"placeholder-select-table": "Select table"
},
"tlssecrets-config": {
"content-tlsssl-client-certificate": "To authenticate with an TLS/SSL client certificate, provide the client certificate here.",
"content-tlsssl-client-key": "To authenticate with a client TLS/SSL certificate, provide the key here.",
"content-tlsssl-root-certificate": "If the selected TLS/SSL mode requires a server root certificate, provide it here",
"tlsssl-client-certificate": "TLS/SSL Client Certificate",
"tlsssl-client-key": "TLS/SSL Client Key",
"tlsssl-root-certificate": "TLS/SSL Root Certificate"
},
"visual-editor": {
"label-filter-by-column-value": "Filter by column value",
"label-group-by-column": "Group by column"
},
"widgets": {
"aria-label-macros-value-selector": "Macros value selector"
}
},
"utils": {
"get-columns-width-indices": {
"label-selected-columns": "Selected columns"
} }
} }
} }
@@ -21,7 +21,7 @@ export function getColumnsWithIndices(query: SQLQuery, fields: SelectableValue[]
return [ return [
{ {
value: '', value: '',
label: t('utils.get-columns-width-indices.label-selected-columns', 'Selected columns'), label: t('grafana-sql.utils.get-columns-width-indices.label-selected-columns', 'Selected columns'),
options, options,
expanded: true, expanded: true,
}, },