I18n: Move eslint rule to package (#105860)
This commit is contained in:
@@ -10,6 +10,7 @@ const testingLibraryPlugin = require('eslint-plugin-testing-library');
|
||||
|
||||
const grafanaConfig = require('@grafana/eslint-config/flat');
|
||||
const grafanaPlugin = require('@grafana/eslint-plugin');
|
||||
const grafanaI18nPlugin = require('@grafana/i18n/eslint-plugin');
|
||||
|
||||
// Include the Grafana config and remove the rules,
|
||||
// as we just want to pull in all of the necessary configuration but not run the rules
|
||||
@@ -65,6 +66,7 @@ module.exports = [
|
||||
'no-barrel-files': barrelPlugin,
|
||||
'@grafana': grafanaPlugin,
|
||||
'testing-library': testingLibraryPlugin,
|
||||
'@grafana/i18n': grafanaI18nPlugin,
|
||||
},
|
||||
linterOptions: {
|
||||
// This reports unused disable directives that we can clean up but
|
||||
|
||||
+4
-2
@@ -13,6 +13,7 @@ const unicornPlugin = require('eslint-plugin-unicorn');
|
||||
|
||||
const grafanaConfig = require('@grafana/eslint-config/flat');
|
||||
const grafanaPlugin = require('@grafana/eslint-plugin');
|
||||
const grafanaI18nPlugin = require('@grafana/i18n/eslint-plugin');
|
||||
|
||||
const bettererConfig = require('./.betterer.eslint.config');
|
||||
const getEnvConfig = require('./scripts/webpack/env-util');
|
||||
@@ -294,6 +295,7 @@ module.exports = [
|
||||
name: 'grafana/i18n-overrides',
|
||||
plugins: {
|
||||
'@grafana': grafanaPlugin,
|
||||
'@grafana/i18n': grafanaI18nPlugin,
|
||||
},
|
||||
files: [
|
||||
'public/app/!(plugins)/**/*.{ts,tsx,js,jsx}',
|
||||
@@ -308,8 +310,8 @@ module.exports = [
|
||||
'**/mock*.{ts,tsx}',
|
||||
],
|
||||
rules: {
|
||||
'@grafana/no-untranslated-strings': ['error', { calleesToIgnore: ['^css$', 'use[A-Z].*'] }],
|
||||
'@grafana/no-translation-top-level': 'error',
|
||||
'@grafana/i18n/no-untranslated-strings': ['error', { calleesToIgnore: ['^css$', 'use[A-Z].*'] }],
|
||||
'@grafana/i18n/no-translation-top-level': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -111,184 +111,3 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
### `theme-token-usage`
|
||||
|
||||
Used to find all instances of `theme` tokens being used in the codebase and emit the counts as metrics. Should **not** be used as an actual lint rule!
|
||||
|
||||
### `no-untranslated-strings`
|
||||
|
||||
Check if strings are marked for translation inside JSX Elements, in certain JSX props, and in certain object properties.
|
||||
|
||||
### Options
|
||||
|
||||
#### `forceFix`
|
||||
|
||||
Allows specifying directories that, if the file is present within, then the rule will automatically fix the errors. This is primarily a workaround to allow for automatic mark up of new violations as the rule evolves.
|
||||
|
||||
#### Example:
|
||||
|
||||
```ts
|
||||
{
|
||||
'@grafana/no-untranslated-strings': ['error', { forceFix: ['app/features/some-feature'] }],
|
||||
}
|
||||
```
|
||||
|
||||
#### `calleesToIgnore`
|
||||
|
||||
Allows specifying regexes for methods that should be ignored when checking if object properties are untranslated.
|
||||
|
||||
This is particularly useful to exclude references to properties such as `label` inside `css()` calls.
|
||||
|
||||
#### Example:
|
||||
|
||||
```ts
|
||||
{
|
||||
'@grafana/no-untranslated-strings': ['error', { calleesToIgnore: ['^css$'] }],
|
||||
}
|
||||
|
||||
// The below would not be reported as an error
|
||||
const foo = css({
|
||||
label: 'test',
|
||||
});
|
||||
|
||||
// The below would still be reported as an error
|
||||
const bar = {
|
||||
label: 'test',
|
||||
};
|
||||
```
|
||||
|
||||
#### JSXText
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<InlineToast placement="top" referenceElement={buttonRef.current}>
|
||||
Copied
|
||||
</InlineToast>
|
||||
|
||||
// Good ✅
|
||||
<InlineToast placement="top" referenceElement={buttonRef.current}>
|
||||
<Trans i18nKey="clipboard-button.inline-toast.success">Copied</Trans>
|
||||
</InlineToast>
|
||||
```
|
||||
|
||||
#### JSXAttributes
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<div title="foo bar" />
|
||||
|
||||
// Good ✅
|
||||
<div title={t('some.key.foo-bar', 'foo bar')} />
|
||||
```
|
||||
|
||||
#### Object properties
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const someConfig = {
|
||||
label: 'Some label',
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const getSomeConfig = () => ({
|
||||
label: t('some.key.label', 'Some label'),
|
||||
});
|
||||
```
|
||||
|
||||
#### Passing variables to translations
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const SearchTitle = ({ term }) => <div>Results for {term}</div>;
|
||||
|
||||
// Good ✅
|
||||
const SearchTitle = ({ term }) => <Trans i18nKey="search-page.results-title">Results for {{ term }}</Trans>;
|
||||
|
||||
// Good ✅ (if you need to interpolate variables inside nested components)
|
||||
const SearchTerm = ({ term }) => <Text color="success">{term}</Text>;
|
||||
const SearchTitle = ({ term }) => (
|
||||
<Trans i18nKey="search-page.results-title">
|
||||
Results for <SearchTerm term={term} />
|
||||
</Trans>
|
||||
);
|
||||
|
||||
// Good ✅ (if you need to interpolate variables and additional translated strings inside nested components)
|
||||
const SearchTitle = ({ term }) => (
|
||||
<Trans i18nKey="search-page.results-title" values={{ myVariable: term }}>
|
||||
Results for <Text color="success">{'{{ myVariable }}'} and this translated text is also in green</Text>
|
||||
</Trans>
|
||||
);
|
||||
```
|
||||
|
||||
#### How to translate props or attributes
|
||||
|
||||
This rule checks if a string is wrapped up by the `Trans` tag, or if certain props contain untranslated strings.
|
||||
We ask for such props to be translated with the `t()` function.
|
||||
|
||||
The below props are checked for untranslated strings:
|
||||
|
||||
- `label`
|
||||
- `description`
|
||||
- `placeholder`
|
||||
- `aria-label`
|
||||
- `title`
|
||||
- `subTitle`
|
||||
- `text`
|
||||
- `tooltip`
|
||||
- `message`
|
||||
- `name`
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<input type="value" placeholder={'Username'} />;
|
||||
|
||||
// Good ✅
|
||||
const placeholder = t('form.username-placeholder', 'Username');
|
||||
return <input type="value" placeholder={placeholder} />;
|
||||
```
|
||||
|
||||
Check more info about how translations work in Grafana in [Internationalization.md](https://github.com/grafana/grafana/blob/main/contribute/internationalization.md)
|
||||
|
||||
### `no-translation-top-level`
|
||||
|
||||
Ensure that `t()` translation method is not used at the top level of a file, outside of a component of method.
|
||||
This is to prevent calling the translation method before it's been instantiated.
|
||||
|
||||
This does not cause an error if a file is lazily loaded, but refactors can cause errors, and it can cause problems in tests.
|
||||
Fix the
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const someTranslatedText = t('some.key', 'Some text');
|
||||
const SomeComponent = () => {
|
||||
return <div title={someTranslatedText} />;
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const SomeComponent = () => {
|
||||
const someTranslatedText = t('some.key', 'Some text');
|
||||
return <div title={someTranslatedText} />;
|
||||
};
|
||||
|
||||
// Bad ❌
|
||||
const someConfigThatHasToBeShared = [{ foo: t('some.key', 'Some text') }];
|
||||
const SomeComponent = () => {
|
||||
return (
|
||||
<div>
|
||||
{someConfigThatHasToBeShared.map((cfg) => {
|
||||
return <div>{cfg.foo}</div>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const someConfigThatHasToBeShared = () => [{ foo: t('some.key', 'Some text') }];
|
||||
const SomeComponent = () => {
|
||||
const configs = someConfigThatHasToBeShared();
|
||||
return (
|
||||
<div>
|
||||
{configs.map((cfg) => {
|
||||
return <div>{cfg.foo}</div>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const noAriaLabelSelectors = require('./rules/no-aria-label-e2e-selectors.cjs');
|
||||
const noBorderRadiusLiteral = require('./rules/no-border-radius-literal.cjs');
|
||||
const noUnreducedMotion = require('./rules/no-unreduced-motion.cjs');
|
||||
const noUntranslatedStrings = require('./rules/no-untranslated-strings.cjs');
|
||||
const noTranslationTopLevel = require('./rules/no-translation-top-level.cjs');
|
||||
const themeTokenUsage = require('./rules/theme-token-usage.cjs');
|
||||
const noRestrictedImgSrcs = require('./rules/no-restricted-img-srcs.cjs');
|
||||
|
||||
@@ -12,8 +10,6 @@ module.exports = {
|
||||
'no-aria-label-selectors': noAriaLabelSelectors,
|
||||
'no-border-radius-literal': noBorderRadiusLiteral,
|
||||
'theme-token-usage': themeTokenUsage,
|
||||
'no-untranslated-strings': noUntranslatedStrings,
|
||||
'no-translation-top-level': noTranslationTopLevel,
|
||||
'no-restricted-img-srcs': noRestrictedImgSrcs,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
"./internal": {
|
||||
"import": "./src/internal/index.ts",
|
||||
"require": "./src/internal/index.ts"
|
||||
},
|
||||
"./eslint-plugin": {
|
||||
"import": "./src/eslint/index.cjs",
|
||||
"require": "./src/eslint/index.cjs"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
# Grafana Internationalization ESLint Rules
|
||||
|
||||
This package also contains custom i18n eslint rules for use within the Grafana codebase and plugins.
|
||||
|
||||
## Rules
|
||||
|
||||
### `no-untranslated-strings`
|
||||
|
||||
Check if strings are marked for translation inside JSX Elements, in certain JSX props, and in certain object properties.
|
||||
|
||||
### Options
|
||||
|
||||
#### `forceFix`
|
||||
|
||||
Allows specifying directories that, if the file is present within, then the rule will automatically fix the errors. This is primarily a workaround to allow for automatic mark up of new violations as the rule evolves.
|
||||
|
||||
#### Example:
|
||||
|
||||
```ts
|
||||
{
|
||||
'@grafana/i18n/no-untranslated-strings': ['error', { forceFix: ['app/features/some-feature'] }],
|
||||
}
|
||||
```
|
||||
|
||||
#### `calleesToIgnore`
|
||||
|
||||
Allows specifying regexes for methods that should be ignored when checking if object properties are untranslated.
|
||||
|
||||
This is particularly useful to exclude references to properties such as `label` inside `css()` calls.
|
||||
|
||||
#### Example:
|
||||
|
||||
```ts
|
||||
{
|
||||
'@grafana/i18n/no-untranslated-strings': ['error', { calleesToIgnore: ['^css$'] }],
|
||||
}
|
||||
|
||||
// The below would not be reported as an error
|
||||
const foo = css({
|
||||
label: 'test',
|
||||
});
|
||||
|
||||
// The below would still be reported as an error
|
||||
const bar = {
|
||||
label: 'test',
|
||||
};
|
||||
```
|
||||
|
||||
#### JSXText
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<InlineToast placement="top" referenceElement={buttonRef.current}>
|
||||
Copied
|
||||
</InlineToast>
|
||||
|
||||
// Good ✅
|
||||
<InlineToast placement="top" referenceElement={buttonRef.current}>
|
||||
<Trans i18nKey="clipboard-button.inline-toast.success">Copied</Trans>
|
||||
</InlineToast>
|
||||
```
|
||||
|
||||
#### JSXAttributes
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<div title="foo bar" />
|
||||
|
||||
// Good ✅
|
||||
<div title={t('some.key.foo-bar', 'foo bar')} />
|
||||
```
|
||||
|
||||
#### Object properties
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const someConfig = {
|
||||
label: 'Some label',
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const getSomeConfig = () => ({
|
||||
label: t('some.key.label', 'Some label'),
|
||||
});
|
||||
```
|
||||
|
||||
#### Passing variables to translations
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const SearchTitle = ({ term }) => <div>Results for {term}</div>;
|
||||
|
||||
// Good ✅
|
||||
const SearchTitle = ({ term }) => <Trans i18nKey="search-page.results-title">Results for {{ term }}</Trans>;
|
||||
|
||||
// Good ✅ (if you need to interpolate variables inside nested components)
|
||||
const SearchTerm = ({ term }) => <Text color="success">{term}</Text>;
|
||||
const SearchTitle = ({ term }) => (
|
||||
<Trans i18nKey="search-page.results-title">
|
||||
Results for <SearchTerm term={term} />
|
||||
</Trans>
|
||||
);
|
||||
|
||||
// Good ✅ (if you need to interpolate variables and additional translated strings inside nested components)
|
||||
const SearchTitle = ({ term }) => (
|
||||
<Trans i18nKey="search-page.results-title" values={{ myVariable: term }}>
|
||||
Results for <Text color="success">{'{{ myVariable }}'} and this translated text is also in green</Text>
|
||||
</Trans>
|
||||
);
|
||||
```
|
||||
|
||||
#### How to translate props or attributes
|
||||
|
||||
This rule checks if a string is wrapped up by the `Trans` tag, or if certain props contain untranslated strings.
|
||||
We ask for such props to be translated with the `t()` function.
|
||||
|
||||
The below props are checked for untranslated strings:
|
||||
|
||||
- `label`
|
||||
- `description`
|
||||
- `placeholder`
|
||||
- `aria-label`
|
||||
- `title`
|
||||
- `subTitle`
|
||||
- `text`
|
||||
- `tooltip`
|
||||
- `message`
|
||||
- `name`
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
<input type="value" placeholder={'Username'} />;
|
||||
|
||||
// Good ✅
|
||||
const placeholder = t('form.username-placeholder', 'Username');
|
||||
return <input type="value" placeholder={placeholder} />;
|
||||
```
|
||||
|
||||
Check more info about how translations work in Grafana in [Internationalization.md](https://github.com/grafana/grafana/blob/main/contribute/internationalization.md)
|
||||
|
||||
### `no-translation-top-level`
|
||||
|
||||
Ensure that `t()` translation method is not used at the top level of a file, outside of a component of method.
|
||||
This is to prevent calling the translation method before it's been instantiated.
|
||||
|
||||
This does not cause an error if a file is lazily loaded, but refactors can cause errors, and it can cause problems in tests.
|
||||
|
||||
```tsx
|
||||
// Bad ❌
|
||||
const someTranslatedText = t('some.key', 'Some text');
|
||||
const SomeComponent = () => {
|
||||
return <div title={someTranslatedText} />;
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const SomeComponent = () => {
|
||||
const someTranslatedText = t('some.key', 'Some text');
|
||||
return <div title={someTranslatedText} />;
|
||||
};
|
||||
|
||||
// Bad ❌
|
||||
const someConfigThatHasToBeShared = [{ foo: t('some.key', 'Some text') }];
|
||||
const SomeComponent = () => {
|
||||
return (
|
||||
<div>
|
||||
{someConfigThatHasToBeShared.map((cfg) => {
|
||||
return <div>{cfg.foo}</div>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// Good ✅
|
||||
const getSomeConfigThatHasToBeShared = () => [{ foo: t('some.key', 'Some text') }];
|
||||
const SomeComponent = () => {
|
||||
const configs = getSomeConfigThatHasToBeShared();
|
||||
return (
|
||||
<div>
|
||||
{configs.map((cfg) => {
|
||||
return <div>{cfg.foo}</div>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
const noUntranslatedStrings = require('./no-untranslated-strings/no-untranslated-strings.cjs');
|
||||
const noTranslationTopLevel = require('./no-translation-top-level/no-translation-top-level.cjs');
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
'no-untranslated-strings': noUntranslatedStrings,
|
||||
'no-translation-top-level': noTranslationTopLevel,
|
||||
},
|
||||
};
|
||||
+1
-1
@@ -7,7 +7,7 @@ const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
|
||||
*/
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(
|
||||
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`
|
||||
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-i18n/src/eslint/README.md#${name}`
|
||||
);
|
||||
|
||||
/**
|
||||
+19
-15
@@ -1,8 +1,8 @@
|
||||
import { RuleTester } from 'eslint';
|
||||
|
||||
import noTranslationTopLevel from '../rules/no-translation-top-level.cjs';
|
||||
import noTranslationTopLevel from './no-translation-top-level.cjs';
|
||||
|
||||
RuleTester.setDefaultConfig({
|
||||
const ruleTester = new RuleTester({
|
||||
languageOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
@@ -14,13 +14,11 @@ RuleTester.setDefaultConfig({
|
||||
},
|
||||
});
|
||||
|
||||
const expectedErrorMessage = 'Do not use the t() function outside of a component or function';
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
// @ts-ignore
|
||||
ruleTester.run('eslint no-translation-top-level', noTranslationTopLevel, {
|
||||
valid: [
|
||||
{
|
||||
name: 'invocation inside component',
|
||||
code: `
|
||||
function Component() {
|
||||
return <div>{t('some.key', 'Some text')}</div>;
|
||||
@@ -28,31 +26,37 @@ function Component() {
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: 'invocation inside function',
|
||||
code: `const foo = () => t('some.key', 'Some text');`,
|
||||
},
|
||||
{
|
||||
code: `const foo = ttt('some.key', 'Some text');`,
|
||||
name: 'invocation inside class component',
|
||||
code: `class Component {
|
||||
render() {
|
||||
return t('some.key', 'Some text');
|
||||
}
|
||||
}`,
|
||||
},
|
||||
{
|
||||
code: `class Component {
|
||||
render() {
|
||||
return t('some.key', 'Some text');
|
||||
}
|
||||
}`,
|
||||
name: 'invocation of something not named t at top level',
|
||||
code: `const foo = ttt('some.key', 'Some text');`,
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
{
|
||||
name: 'invocation at top level',
|
||||
code: `const thing = t('some.key', 'Some text');`,
|
||||
errors: [{ message: expectedErrorMessage }],
|
||||
errors: 1,
|
||||
},
|
||||
{
|
||||
name: 'invocation in array',
|
||||
code: `const things = [t('some.key', 'Some text')];`,
|
||||
errors: [{ message: expectedErrorMessage }],
|
||||
errors: 1,
|
||||
},
|
||||
{
|
||||
name: 'invocation in object',
|
||||
code: `const objectThings = [{foo: t('some.key', 'Some text')}];`,
|
||||
errors: [{ message: expectedErrorMessage }],
|
||||
errors: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
+5
-2
@@ -18,7 +18,7 @@ const {
|
||||
const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
|
||||
|
||||
const createRule = ESLintUtils.RuleCreator(
|
||||
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-eslint-rules/README.md#${name}`
|
||||
(name) => `https://github.com/grafana/grafana/blob/main/packages/grafana-i18n/src/eslint/README.md#${name}`
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -224,7 +224,10 @@ const noUntranslatedStrings = createRule({
|
||||
// We don't want to report if the parent has a text node,
|
||||
// as we'd end up doing it twice. This makes it awkward for us to auto fix
|
||||
const parentHasText = parentHasChildren
|
||||
? parent.children.some((child) => child.type === AST_NODE_TYPES.JSXText && getNodeValue(child).trim())
|
||||
? parent.children.some((child) => {
|
||||
const childValue = getNodeValue(child).trim();
|
||||
return child.type === AST_NODE_TYPES.JSXText && childValue && !isStringNonAlphanumeric(childValue);
|
||||
})
|
||||
: false;
|
||||
|
||||
if (untranslatedTextNodes.length && !parentHasText) {
|
||||
+30
-13
@@ -1,8 +1,17 @@
|
||||
import { RuleTester } from 'eslint';
|
||||
|
||||
import noUntranslatedStrings from '../rules/no-untranslated-strings.cjs';
|
||||
import noUntranslatedStrings from './no-untranslated-strings.cjs';
|
||||
|
||||
RuleTester.setDefaultConfig({
|
||||
const filename = 'public/app/features/some-feature/nested/SomeFile.tsx';
|
||||
|
||||
const packageName = '@grafana/i18n';
|
||||
|
||||
const TRANS_IMPORT = `import { Trans } from '${packageName}';`;
|
||||
const T_IMPORT = `import { t } from '${packageName}/internal';`;
|
||||
const USE_TRANSLATE_IMPORT = `import { useTranslate } from '${packageName}';`;
|
||||
const TRANS_AND_USE_TRANSLATE_IMPORT = `import { Trans, useTranslate } from '${packageName}';`;
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
languageOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
@@ -14,17 +23,7 @@ RuleTester.setDefaultConfig({
|
||||
},
|
||||
});
|
||||
|
||||
const filename = 'public/app/features/some-feature/nested/SomeFile.tsx';
|
||||
|
||||
const packageName = '@grafana/i18n';
|
||||
|
||||
const TRANS_IMPORT = `import { Trans } from '${packageName}';`;
|
||||
const T_IMPORT = `import { t } from '${packageName}/internal';`;
|
||||
const USE_TRANSLATE_IMPORT = `import { useTranslate } from '${packageName}';`;
|
||||
const TRANS_AND_USE_TRANSLATE_IMPORT = `import { Trans, useTranslate } from '${packageName}';`;
|
||||
|
||||
const ruleTester = new RuleTester();
|
||||
|
||||
//@ts-ignore
|
||||
ruleTester.run('eslint no-untranslated-strings', noUntranslatedStrings, {
|
||||
test: [],
|
||||
valid: [
|
||||
@@ -212,6 +211,24 @@ const Foo = () => <div><Trans i18nKey="some-feature.foo.untranslated-text">Untra
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: 'non-alphanumeric characters outside child element',
|
||||
code: `
|
||||
const Foo = () => {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
something untranslated but i'm a naughty dev and
|
||||
I put a bunch of non-alphanumeric characters outside of the div
|
||||
</div>
|
||||
.?!;
|
||||
</>
|
||||
)
|
||||
}`,
|
||||
filename,
|
||||
errors: 1,
|
||||
},
|
||||
|
||||
{
|
||||
name: 'Text inside JSXElement, not in a function',
|
||||
code: `
|
||||
@@ -267,7 +267,6 @@ export const MultiCombobox = <T extends string | number>(props: MultiComboboxPro
|
||||
))}
|
||||
{selectedItems.length > visibleItems.length && (
|
||||
<Box display="flex" direction="row" marginLeft={0.5} gap={1} ref={counterMeasureRef}>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
<Text>...</Text>
|
||||
<Tooltip
|
||||
interactive
|
||||
|
||||
@@ -61,7 +61,7 @@ const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: Custom
|
||||
<FormField
|
||||
label={t('grafana-ui.data-source-settings.custom-headers-header', 'Header')}
|
||||
name="name"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="X-Custom-Header"
|
||||
labelWidth={5}
|
||||
value={header.name || ''}
|
||||
|
||||
@@ -98,7 +98,7 @@ export const TLSAuthSettings = ({ dataSourceConfig, onChange }: HttpSettingsBase
|
||||
label={t('grafana-ui.data-source-settings.tls-server-name-label', 'ServerName')}
|
||||
labelWidth={7}
|
||||
inputWidth={30}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="domain.example.com"
|
||||
value={hasServerName && dataSourceConfig.jsonData.serverName}
|
||||
onChange={onServerNameLabelChange}
|
||||
|
||||
@@ -24,14 +24,14 @@ export const BorderRadiusContainer = ({
|
||||
return (
|
||||
<Stack direction="column" alignItems="center" gap={4}>
|
||||
<Stack alignItems="center">
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Text variant="code">getInternalRadius</Text>
|
||||
<div className={styles.baseForInternal}>
|
||||
<div className={styles.internalContainer} />
|
||||
</div>
|
||||
</Stack>
|
||||
<Stack alignItems="center">
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Text variant="code">getExternalRadius</Text>
|
||||
<div className={styles.externalContainer}>
|
||||
<div className={styles.baseForExternal} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
/** @jsxImportSource @emotion/react */
|
||||
import { css, cx } from '@emotion/css';
|
||||
import classnames from 'classnames';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { useState } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
@@ -36,7 +36,7 @@ export const UsersIndicator = ({ users, onClick, limit = 4 }: UsersIndicatorProp
|
||||
{limitReached && (
|
||||
<UserIcon onClick={onClick} userView={{ user: { name: 'Extra users' }, lastActiveAt: '' }} showTooltip={false}>
|
||||
{tooManyUsers
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
'...'
|
||||
: `+${extraUsers}`}
|
||||
</UserIcon>
|
||||
|
||||
@@ -179,7 +179,7 @@ export const ScaleDistributionEditor = ({ value, onChange }: StandardEditorProps
|
||||
{type === ScaleDistribution.Symlog && (
|
||||
<Field label={t('grafana-ui.axis-builder.linear-threshold', 'Linear threshold')} style={{ marginBottom: 0 }}>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1"
|
||||
value={value?.linearThreshold}
|
||||
onChange={(v) => {
|
||||
|
||||
@@ -139,7 +139,7 @@ function HistoryEntryAppView({ entry, isSelected, onClick }: ItemProps) {
|
||||
<Text key={index}>
|
||||
{breadcrumb.text}{' '}
|
||||
{index !== breadcrumbs.length - 1
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
'> '
|
||||
: ''}
|
||||
</Text>
|
||||
|
||||
@@ -56,7 +56,7 @@ export const ActionVariablesEditor = ({ value, onChange }: Props) => {
|
||||
|
||||
const variableTypeOptions: ComboboxOption[] = [
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'string',
|
||||
value: ActionVariableType.String,
|
||||
},
|
||||
|
||||
@@ -200,7 +200,7 @@ const FeatureListing = () => {
|
||||
</Item>
|
||||
<Item title={t('admin.feature-listing.title-enterprise-plugins', 'Enterprise plugins')}>
|
||||
<List nested={true}>
|
||||
{/* eslint-disable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable @grafana/i18n/no-untranslated-strings */}
|
||||
<Item title="Oracle" />
|
||||
<Item title="Splunk" />
|
||||
<Item title="Service Now" />
|
||||
@@ -216,7 +216,7 @@ const FeatureListing = () => {
|
||||
<Item title="Salesforce" />
|
||||
<Item title="Snowflake" />
|
||||
<Item title="Wavefront" />
|
||||
{/* eslint-enable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-enable @grafana/i18n/no-untranslated-strings */}
|
||||
</List>
|
||||
</Item>
|
||||
</List>
|
||||
|
||||
@@ -99,7 +99,7 @@ export const LdapDrawerComponent = ({
|
||||
<Trans i18nKey="ldap-drawer.extra-security-section.use-ssl-tooltip">
|
||||
For a complete list of supported ciphers and TLS versions, refer to:
|
||||
</Trans>{' '}
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<TextLink style={{ fontSize: 'inherit' }} href="https://go.dev/src/crypto/tls/cipher_suites.go" external>
|
||||
https://go.dev/src/crypto/tls/cipher_suites.go
|
||||
</TextLink>
|
||||
@@ -145,7 +145,7 @@ export const LdapDrawerComponent = ({
|
||||
>
|
||||
<Input
|
||||
id="port"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="389"
|
||||
type="number"
|
||||
{...register(`${serverConfig}.port`, { valueAsNumber: true })}
|
||||
@@ -160,7 +160,7 @@ export const LdapDrawerComponent = ({
|
||||
>
|
||||
<Input
|
||||
id="timeout"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="10"
|
||||
type="number"
|
||||
{...register(`${serverConfig}.timeout`, { valueAsNumber: true })}
|
||||
@@ -414,7 +414,7 @@ export const LdapDrawerComponent = ({
|
||||
<Field label={t('ldap-drawer.extra-security-section.client-cert-label', 'Client certificate path')}>
|
||||
<Input
|
||||
id="client-cert"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/path/to/client_cert.pem"
|
||||
type="text"
|
||||
{...register(`${serverConfig}.client_cert`)}
|
||||
|
||||
@@ -413,7 +413,6 @@ interface FrameProps extends Pick<ExpressionProps, 'isAlertCondition'> {
|
||||
|
||||
const OpeningBracket = () => <span>{'{'}</span>;
|
||||
const ClosingBracket = () => <span>{'}'}</span>;
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
const Quote = () => <span>"</span>;
|
||||
const Equals = () => <span>{'='}</span>;
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ export function PromDurationDocs() {
|
||||
<div>
|
||||
<Trans i18nKey="alerting.prom-duration-docs.multiple-units-combined">Multiple units combined</Trans>
|
||||
</div>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<code>1m30s, 2h30m20s, 1w2d</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+8
-8
@@ -17,7 +17,7 @@ import { SuggestionDefinition } from './suggestionDefinition';
|
||||
export function getGlobalSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
const kind = monaco.languages.CompletionItemKind.Field;
|
||||
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
return [
|
||||
{
|
||||
label: 'Alerts',
|
||||
@@ -39,14 +39,14 @@ export function getGlobalSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
{ label: 'GroupKey', kind, detail: 'string' },
|
||||
{ label: 'TruncatedAlerts', kind, detail: 'integer' },
|
||||
];
|
||||
/* eslint-enable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
}
|
||||
|
||||
// Suggestions that are valid only in the scope of an alert (e.g. in the .Alerts loop)
|
||||
export function getAlertSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
const kind = monaco.languages.CompletionItemKind.Field;
|
||||
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
return [
|
||||
{
|
||||
label: { label: 'Status', detail: '(Alert)', description: 'string' },
|
||||
@@ -148,26 +148,26 @@ export function getAlertSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
),
|
||||
},
|
||||
];
|
||||
/* eslint-enable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
}
|
||||
|
||||
// Suggestions for .Alerts
|
||||
export function getAlertsSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
const kind = monaco.languages.CompletionItemKind.Field;
|
||||
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
return [
|
||||
{ label: 'Firing', kind, detail: 'Alert[]' },
|
||||
{ label: 'Resolved', kind, detail: 'Alert[]' },
|
||||
];
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
}
|
||||
|
||||
// Suggestions for the KeyValue types
|
||||
export function getKeyValueSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
const kind = monaco.languages.CompletionItemKind.Field;
|
||||
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
return [
|
||||
{ label: 'SortedPairs', kind, detail: '[]KeyValue' },
|
||||
{ label: 'Names', kind, detail: '[]string' },
|
||||
@@ -178,7 +178,7 @@ export function getKeyValueSuggestions(monaco: Monaco): SuggestionDefinition[] {
|
||||
kind: monaco.languages.CompletionItemKind.Method,
|
||||
},
|
||||
];
|
||||
/* eslint-enable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
}
|
||||
|
||||
export const snippets = {
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ export const SubformArrayField = ({
|
||||
<div className={styles.wrapper}>
|
||||
<CollapsibleSection
|
||||
className={styles.collapsibleSection}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label={`${option.label} (${fields.length})`}
|
||||
description={option.description}
|
||||
>
|
||||
|
||||
@@ -182,7 +182,7 @@ const AnnotationsStep = () => {
|
||||
{...register(`annotations.${index}.value`)}
|
||||
placeholder={
|
||||
isUrl
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
'https://'
|
||||
: (annotationField.key &&
|
||||
t('alerting.annotations-step.placeholder-value-input', 'Enter a {{key}}...', {
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ export const GroupAndNamespaceFields = ({ rulesSourceName }: Props) => {
|
||||
label={t('alerting.group-and-namespace-fields.namespace-picker-label-namespace', 'Namespace')}
|
||||
// Disable translations as we don't intend to use this dropdown longterm,
|
||||
// so avoiding us adding translations for the sake of it
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
description="Type to search for an existing namespace or create a new one"
|
||||
error={errors.namespace?.message}
|
||||
invalid={!!errors.namespace?.message}
|
||||
@@ -82,7 +82,7 @@ export const GroupAndNamespaceFields = ({ rulesSourceName }: Props) => {
|
||||
label={t('alerting.group-and-namespace-fields.group-picker-label-group', 'Group')}
|
||||
// Disable translations as we don't intend to use this dropdown longterm,
|
||||
// so avoiding us adding translations for the sake of it
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
description="Type to search for an existing group or create a new one"
|
||||
error={errors.group?.message}
|
||||
invalid={!!errors.group?.message}
|
||||
|
||||
@@ -118,7 +118,7 @@ const EvaluationBehaviorSummary = ({ rule }: EvaluationBehaviorSummaryProps) =>
|
||||
>
|
||||
<Tooltip
|
||||
placement="top"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
content={`${dateTimeFormat(lastEvaluation, { format: 'YYYY-MM-DD HH:mm:ss' })}`}
|
||||
theme="info"
|
||||
>
|
||||
@@ -138,7 +138,7 @@ const EvaluationBehaviorSummary = ({ rule }: EvaluationBehaviorSummaryProps) =>
|
||||
>
|
||||
<Tooltip
|
||||
placement="top"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
content={`${lastEvaluationDuration}s`}
|
||||
theme="info"
|
||||
>
|
||||
|
||||
@@ -268,7 +268,7 @@ function useColumns(
|
||||
nextEvalInfo && (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
content={`${nextEvalInfo?.fullDate}`}
|
||||
theme="info"
|
||||
>
|
||||
|
||||
@@ -59,7 +59,7 @@ export const SilencesFilter = () => {
|
||||
</Trans>
|
||||
</div>
|
||||
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<pre>severity=critical, env=production</pre>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ function useColumns(alertManagerSourceName: string) {
|
||||
<span data-testid="alerts">
|
||||
{Array.isArray(silencedAlerts)
|
||||
? silencedAlerts.length
|
||||
: // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
: // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
'-'}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
import { PluginLoadingStrategy, PluginMeta, PluginType } from '@grafana/data';
|
||||
import { AppPluginConfig, setPluginComponentsHook, setPluginLinksHook } from '@grafana/runtime';
|
||||
import { SupportedPlugin } from 'app/features/alerting/unified/types/pluginBridges';
|
||||
|
||||
@@ -433,13 +433,13 @@ export function fieldMap(provider: string): Record<string, FieldData> {
|
||||
),
|
||||
multi: false,
|
||||
options: [
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
{ value: 'AutoDetect', label: 'AutoDetect' },
|
||||
{ value: 'InParams', label: 'InParams' },
|
||||
{ value: 'InHeader', label: 'InHeader' },
|
||||
],
|
||||
defaultValue: { value: 'AutoDetect', label: 'AutoDetect' },
|
||||
/* eslint-enable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
},
|
||||
tokenUrl: {
|
||||
label: tokenURLLabel,
|
||||
@@ -914,7 +914,7 @@ function orgMappingDescription(provider: string): string {
|
||||
|
||||
function clientAuthenticationOptions(provider: string): Array<SelectableValue<string>> {
|
||||
// Other options are purposefully not translated
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
switch (provider) {
|
||||
case 'azuread':
|
||||
return [
|
||||
@@ -930,5 +930,5 @@ function clientAuthenticationOptions(provider: string): Array<SelectableValue<st
|
||||
{ value: 'client_secret_post', label: 'Client secret' },
|
||||
];
|
||||
}
|
||||
/* eslint-enable @grafana/no-untranslated-strings */
|
||||
/* eslint-enable @grafana/i18n/no-untranslated-strings */
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ export const settingsViewable = (scene: Scene) => ({
|
||||
|
||||
const rect = moveable.getRect();
|
||||
return (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
<div
|
||||
key={'settings-viewable'}
|
||||
className={'moveable-settings'}
|
||||
@@ -70,7 +69,7 @@ export const dimensionViewable = {
|
||||
render(moveable: MoveableManagerInterface<unknown, unknown>, React: Renderer) {
|
||||
const rect = moveable.getRect();
|
||||
return (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
<div
|
||||
key={'dimension-viewable'}
|
||||
className={'moveable-dimension'}
|
||||
|
||||
@@ -29,7 +29,7 @@ export const frameItemDummy: CanvasElementItem = {
|
||||
|
||||
display: () => {
|
||||
// never shown to end user
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
return <div>FRAME!</div>;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -54,7 +54,6 @@ export const ResultItem = React.forwardRef(
|
||||
{!hasCommandOrLink(ancestor) && (
|
||||
<>
|
||||
<span className={styles.breadcrumbAncestor}>{ancestor.name}</span>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
<span className={styles.breadcrumbSeparator}>›</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -103,7 +103,7 @@ function getGlobalActions(): CommandPaletteAction[] {
|
||||
];
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// eslint-disable @grafana/no-untranslated-strings
|
||||
// eslint-disable @grafana/i18n/no-untranslated-strings
|
||||
const section = 'Dev tooling';
|
||||
const currentState = currentMockApiState();
|
||||
const mockApiAction = currentState ? 'Disable' : 'Enable';
|
||||
@@ -128,7 +128,7 @@ function getGlobalActions(): CommandPaletteAction[] {
|
||||
togglePseudoLocale();
|
||||
},
|
||||
});
|
||||
// eslint-enable @grafana/no-untranslated-strings
|
||||
// eslint-enable @grafana/i18n/no-untranslated-strings
|
||||
}
|
||||
|
||||
return actions;
|
||||
|
||||
@@ -76,7 +76,7 @@ export const ConfigureCorrelationSourceForm = () => {
|
||||
<span className={styles.variable} key={i}>
|
||||
{name}
|
||||
{i < variables.length - 1
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
', '
|
||||
: ''}
|
||||
</span>
|
||||
|
||||
@@ -138,7 +138,7 @@ const TransformationEditorRow = (props: Props) => {
|
||||
<Label htmlFor={`config.transformations.${defaultValue.id}.expression`}>
|
||||
<Trans i18nKey="correlations.transform-row.expression-label">Expression</Trans>
|
||||
{getSupportedTransTypeDetails(watch(`config.transformations.${index}.type`)).expressionDetails.required
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
' *'
|
||||
: ''}
|
||||
</Label>
|
||||
|
||||
@@ -24,7 +24,7 @@ export function EmbeddedDashboardTestPage() {
|
||||
layout={PageLayoutType.Canvas}
|
||||
>
|
||||
{/* this is a test page, no need to translate */}
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Box paddingY={2}>Internal url state: {state}</Box>
|
||||
<EmbeddedDashboard uid="lVE-2YFMz" initialState={state} onStateChange={setState} />
|
||||
</Page>
|
||||
|
||||
@@ -80,7 +80,6 @@ function VariableList({ set }: { set: SceneVariableSet }) {
|
||||
// TODO fix keyboard a11y here
|
||||
// eslint-disable-next-line jsx-a11y/no-static-element-interactions,jsx-a11y/click-events-have-key-events
|
||||
<div className={styles.variableItem} key={variable.state.name} onClick={() => onEditVariable(variable)}>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
<Text>${variable.state.name}</Text>
|
||||
<Stack direction="row" gap={1} alignItems="center">
|
||||
<Button variant="primary" size="sm" fill="outline">
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ export function CustomVariableForm({
|
||||
<VariableTextAreaField
|
||||
name="Values separated by comma"
|
||||
defaultValue={query}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1, 10, mykey : myvalue, myvalue, escaped\,value"
|
||||
onBlur={onQueryChange}
|
||||
required
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ export function DataSourceVariableForm({
|
||||
<VariableTextField
|
||||
defaultValue={regex}
|
||||
name="Instance name filter"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/.*-(.*)-.*/"
|
||||
onBlur={onRegExBlur}
|
||||
description={
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ export function IntervalVariableForm({
|
||||
<VariableTextField
|
||||
defaultValue={intervals}
|
||||
name="Values"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1m,10m,1h,6h,1d,7d"
|
||||
onBlur={onIntervalsChange}
|
||||
testId={selectors.pages.Dashboard.Settings.Variables.Edit.IntervalVariable.intervalsValueInput}
|
||||
@@ -91,7 +91,7 @@ export function IntervalVariableForm({
|
||||
'dashboard-scene.interval-variable-form.description-calculated-value-below-threshold',
|
||||
'The calculated value will not go below this threshold'
|
||||
)}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="10s"
|
||||
onChange={onAutoMinIntervalChanged}
|
||||
width={11}
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ export function QueryVariableEditorForm({
|
||||
</Trans>
|
||||
</div>
|
||||
}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/.*-(?<text>.*)-(?<value>.*)-.*/"
|
||||
onBlur={onRegExChange}
|
||||
testId={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2}
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ export function Editor({ variable }: { variable: QueryVariable }) {
|
||||
</Trans>
|
||||
</div>
|
||||
}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/.*-(?<text>.*)-(?<value>.*)-.*/"
|
||||
onBlur={onRegExChange}
|
||||
testId={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2}
|
||||
|
||||
@@ -106,7 +106,7 @@ export class TimePickerSettings extends PureComponent<Props, State> {
|
||||
<Input
|
||||
id="now-delay-input"
|
||||
invalid={!this.state.isNowDelayValid}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="0m"
|
||||
onChange={this.onNowDelayChange}
|
||||
defaultValue={this.props.nowDelay}
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ export const EmailSharingConfiguration = ({ dashboard }: { dashboard: DashboardM
|
||||
<div className={styles.emailContainer}>
|
||||
<Input
|
||||
className={styles.emailInput}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="me@example.com"
|
||||
autoCapitalize="none"
|
||||
{...register('email', {
|
||||
|
||||
+1
-1
@@ -217,7 +217,7 @@ export const TransformationOperationRow = ({
|
||||
<QueryOperationRow
|
||||
id={id}
|
||||
index={index}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
title={`${index + 1} - ${uiConfig.name}`}
|
||||
draggable
|
||||
actions={renderActions}
|
||||
|
||||
@@ -128,7 +128,7 @@ export const ResourceDimensionEditor = (
|
||||
labelWidth={labelWidth}
|
||||
grow={true}
|
||||
>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings*/}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings*/}
|
||||
<div>TODO mappings editor!</div>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
|
||||
@@ -191,10 +191,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
|
||||
enableNamedColors={true}
|
||||
/>
|
||||
</div>
|
||||
{isPercent && (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
<div className={styles.percentIcon}>%</div>
|
||||
)}
|
||||
{isPercent && <div className={styles.percentIcon}>%</div>}
|
||||
</div>
|
||||
}
|
||||
suffix={
|
||||
|
||||
@@ -123,7 +123,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
|
||||
|
||||
const specialMatchOptions: Array<SelectableValue<SpecialValueMatch>> = [
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'Null',
|
||||
value: SpecialValueMatch.Null,
|
||||
description: t(
|
||||
@@ -132,7 +132,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
|
||||
),
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'NaN',
|
||||
value: SpecialValueMatch.NaN,
|
||||
description: t(
|
||||
@@ -141,7 +141,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
|
||||
),
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'Null + NaN',
|
||||
value: SpecialValueMatch.NullAndNaN,
|
||||
description: t(
|
||||
@@ -150,7 +150,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
|
||||
),
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'True',
|
||||
value: SpecialValueMatch.True,
|
||||
description: t(
|
||||
@@ -159,7 +159,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl
|
||||
),
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label: 'False',
|
||||
value: SpecialValueMatch.False,
|
||||
description: t(
|
||||
|
||||
@@ -108,7 +108,7 @@ export function ExploreRunQueryButton({
|
||||
runQuery(pane[0]);
|
||||
onClick?.();
|
||||
}}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label={`${paneLabel}: ${buttonText.translation}`}
|
||||
disabled={isInvalid || pane[0] === undefined}
|
||||
/>
|
||||
|
||||
@@ -78,11 +78,11 @@ export const LogsMetaRow = memo(
|
||||
|
||||
const downloadMenu = (
|
||||
<Menu>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Menu.Item label="txt" onClick={() => download(DownloadFormat.Text)} />
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Menu.Item label="json" onClick={() => download(DownloadFormat.Json)} />
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Menu.Item label="csv" onClick={() => download(DownloadFormat.CSV)} />
|
||||
</Menu>
|
||||
);
|
||||
|
||||
+2
-2
@@ -216,7 +216,7 @@ export const SpanFilters = memo((props: SpanFilterProps) => {
|
||||
ariaLabel="Select min span duration"
|
||||
onChange={(val) => setSpanFiltersSearch({ ...search, from: val })}
|
||||
isInvalidError="Invalid duration"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="e.g. 100ms, 1.2s"
|
||||
width={18}
|
||||
value={search.from || ''}
|
||||
@@ -233,7 +233,7 @@ export const SpanFilters = memo((props: SpanFilterProps) => {
|
||||
ariaLabel="Select max span duration"
|
||||
onChange={(val) => setSpanFiltersSearch({ ...search, to: val })}
|
||||
isInvalidError="Invalid duration"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="e.g. 100ms, 1.2s"
|
||||
width={18}
|
||||
value={search.to || ''}
|
||||
|
||||
+2
-2
@@ -157,7 +157,7 @@ export const TracePageHeader = memo((props: TracePageHeaderProps) => {
|
||||
)}
|
||||
{method && method.length > 0 && (
|
||||
<Tooltip
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
content="http.method"
|
||||
interactive={true}
|
||||
>
|
||||
@@ -168,7 +168,7 @@ export const TracePageHeader = memo((props: TracePageHeaderProps) => {
|
||||
)}
|
||||
{status && status.length > 0 && (
|
||||
<Tooltip
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
content="http.status_code"
|
||||
interactive={true}
|
||||
>
|
||||
|
||||
+5
-1
@@ -108,7 +108,11 @@ export default function AccordianLogs({
|
||||
return (
|
||||
<div className={styles.AccordianLogs}>
|
||||
<HeaderComponent className={styles.AccordianLogsHeader} {...headerProps}>
|
||||
{arrow} <strong>Events</strong> ({logs.length})
|
||||
{arrow}{' '}
|
||||
<strong>
|
||||
<Trans i18nKey="explore.accordian-logs.events">Events</Trans>
|
||||
</strong>{' '}
|
||||
({logs.length})
|
||||
</HeaderComponent>
|
||||
{isOpen && (
|
||||
<div className={styles.AccordianLogsContent}>
|
||||
|
||||
@@ -17,7 +17,7 @@ export function getExploreExtensionConfigs(): PluginExtensionAddedLinkConfig[] {
|
||||
return [
|
||||
createAddedLinkConfig<PluginExtensionExploreContext>({
|
||||
// This is called at the top level, so will break if we add a translation here 😱
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
title: 'Add to dashboard',
|
||||
description: 'Use the query and panel from explore and create/add it to a dashboard',
|
||||
targets: [PluginExtensionPoints.ExploreToolbarAction],
|
||||
@@ -44,9 +44,9 @@ export function getExploreExtensionConfigs(): PluginExtensionAddedLinkConfig[] {
|
||||
}),
|
||||
createAddedLinkConfig<PluginExtensionExploreContext>({
|
||||
// This is called at the top level, so will break if we add a translation here 😱
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
title: 'Add correlation',
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
description: 'Create a correlation from this query',
|
||||
targets: [PluginExtensionPoints.ExploreToolbarAction],
|
||||
icon: 'link',
|
||||
|
||||
@@ -106,7 +106,7 @@ export const SignupInvitedPage = () => {
|
||||
label={t('invites.signup-invited-page.label-email', 'Email')}
|
||||
>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="email@example.com"
|
||||
{...register('email', {
|
||||
required: 'Email is required',
|
||||
|
||||
@@ -165,7 +165,7 @@ class UnthemedDashboardImport extends PureComponent<Props> {
|
||||
const styles = importStyles(this.props.theme);
|
||||
|
||||
const GcomDashboardsLink = () => (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
<TextLink variant="bodySmall" href="https://grafana.com/grafana/dashboards/" external>
|
||||
grafana.com/dashboards
|
||||
</TextLink>
|
||||
|
||||
@@ -17,7 +17,7 @@ export function AlertWithTraceID(props: AlertWithTraceIDProps) {
|
||||
|
||||
{traceID && (
|
||||
/* Deliberately don't want to translate 'Trace ID' */
|
||||
/* eslint-disable-next-line @grafana/no-untranslated-strings */
|
||||
/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */
|
||||
<Text element="p" color="secondary" variant="bodySmall">
|
||||
Trace ID: {traceID}
|
||||
</Text>
|
||||
|
||||
@@ -79,7 +79,7 @@ export const UserInviteForm = () => {
|
||||
error={!!errors.loginOrEmail ? 'Email or username is required' : undefined}
|
||||
label={t('org.user-invite-form.label-email-or-username', 'Email or username')}
|
||||
>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Input {...register('loginOrEmail', { required: true })} placeholder="email@example.com" />
|
||||
</Field>
|
||||
<Field invalid={!!errors.name} label={t('org.user-invite-form.label-name', 'Name')}>
|
||||
|
||||
@@ -246,7 +246,7 @@ export function PluginDetailsPanel(props: Props): React.ReactElement | null {
|
||||
This feature is for reporting malicious or harmful behaviour within plugins. For plugin concerns, email
|
||||
us at:{' '}
|
||||
</Trans>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<TextLink href="mailto:integrations+report-plugin@grafana.com">integrations@grafana.com</TextLink>
|
||||
</Text>
|
||||
<Text>
|
||||
|
||||
@@ -13,9 +13,9 @@ PluginPageContext.displayName = 'PluginPageContext';
|
||||
function getInitialPluginPageContext(): PluginPageContextType {
|
||||
return {
|
||||
sectionNav: {
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
main: { text: 'Plugin page' },
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
node: { text: 'Plugin page' },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -377,7 +377,7 @@ export function createExtensionSubMenu(extensions: PluginExtensionLink[]): Panel
|
||||
if (uncategorized.length > 0) {
|
||||
if (subMenu.length > 0) {
|
||||
subMenu.push({
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
text: 'divider',
|
||||
type: 'divider',
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ export function TokenPermissionsInfo() {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{/* GitHub UI is English only, so these strings are not translated */}
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable @grafana/i18n/no-untranslated-strings */}
|
||||
<Stack gap={0.5} wrap={'wrap'}>
|
||||
<Trans i18nKey="provisioning.token-permissions-info.go-to">Go to</Trans>
|
||||
<TextLink external href="https://github.com/settings/personal-access-tokens/new">
|
||||
@@ -20,21 +20,22 @@ export function TokenPermissionsInfo() {
|
||||
<strong>"Fine-grained token".</strong>
|
||||
<Trans i18nKey="provisioning.token-permissions-info.make-sure">Make sure to include these permissions</Trans>:
|
||||
</Stack>
|
||||
{/* eslint-enable @grafana/i18n/no-untranslated-strings */}
|
||||
|
||||
<ul className={styles.permissionsList}>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<li>
|
||||
Content: <span className={styles.accessLevel}>Read and write</span>
|
||||
</li>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<li>
|
||||
Metadata: <span className={styles.accessLevel}>Read only</span>
|
||||
</li>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<li>
|
||||
Pull requests: <span className={styles.accessLevel}>Read and write</span>
|
||||
</li>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<li>
|
||||
Webhooks: <span className={styles.accessLevel}>Read and write</span>
|
||||
</li>
|
||||
|
||||
@@ -237,7 +237,6 @@ export function ProvisioningWizard({ type }: { type: RepoType }) {
|
||||
<FormPrompt onDiscard={handleCancel} confirmRedirect={isDirty && activeStep !== 'finish' && !isCancelling} />
|
||||
<Stack direction="column">
|
||||
<Box marginBottom={2}>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
<Text element="h2">
|
||||
{currentStepIndex + 1}. {currentStepConfig?.title}
|
||||
</Text>
|
||||
|
||||
@@ -138,7 +138,6 @@ const renderDataSource = <TQuery extends DataQuery>(
|
||||
const { alerting, dataSource, onChangeDataSource } = props;
|
||||
|
||||
if (!onChangeDataSource) {
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
return <em className={styles.contextInfo}>({dataSource.name})</em>;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
<Input
|
||||
id="cache-timeout-id"
|
||||
type="text"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="60"
|
||||
spellCheck={false}
|
||||
onBlur={onCacheTimeoutBlur}
|
||||
@@ -193,7 +193,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
</InlineLabel>
|
||||
<Input
|
||||
type="number"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={`${dataSource.cachingConfig.TTLMs}`}
|
||||
spellCheck={false}
|
||||
onBlur={onQueryCachingTTLBlur}
|
||||
@@ -226,7 +226,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
<Input
|
||||
id="max-data-points-input"
|
||||
type="number"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={`${realMd}`}
|
||||
spellCheck={false}
|
||||
onBlur={onMaxDataPointsBlur}
|
||||
@@ -267,7 +267,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
<Input
|
||||
id="min-interval-input"
|
||||
type="text"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={`${minIntervalOnDs}`}
|
||||
spellCheck={false}
|
||||
onBlur={onMinIntervalBlur}
|
||||
@@ -359,7 +359,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
<Input
|
||||
id="relative-time-input"
|
||||
type="text"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1h"
|
||||
onChange={onRelativeTimeChange}
|
||||
onBlur={onOverrideTime}
|
||||
@@ -385,7 +385,7 @@ export const QueryGroupOptionsEditor = React.memo(({ options, dataSource, data,
|
||||
<Input
|
||||
id="time-shift-input"
|
||||
type="text"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1h"
|
||||
onChange={onTimeShiftChange}
|
||||
onBlur={onTimeShift}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable @grafana/no-untranslated-strings */
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { usePluginLinks } from '@grafana/runtime';
|
||||
import { Button, LinkButton, Stack, Text } from '@grafana/ui';
|
||||
|
||||
@@ -81,7 +81,7 @@ export const CreateTeam = (): JSX.Element => {
|
||||
'This is optional and is primarily used for allowing custom team avatars'
|
||||
)}
|
||||
>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Input {...register('email')} type="email" id="team-email" placeholder="email@test.com" />
|
||||
</Field>
|
||||
</FieldSet>
|
||||
|
||||
@@ -78,7 +78,7 @@ export const TeamSettings = ({ team, updateTeam }: Props) => {
|
||||
)}
|
||||
disabled={!canWriteTeamSettings}
|
||||
>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */}
|
||||
<Input {...register('email')} placeholder="team@email.com" type="email" id="email-input" />
|
||||
</Field>
|
||||
<Button type="submit" disabled={!canWriteTeamSettings}>
|
||||
|
||||
+1
-6
@@ -59,11 +59,7 @@ export const UnaryOperationEditor = (props: {
|
||||
>
|
||||
<Select options={ops} value={unary?.operator ?? ops[0].value} onChange={onUnaryOperationChanged} />
|
||||
</InlineField>
|
||||
<InlineField
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
label="("
|
||||
labelWidth={2}
|
||||
>
|
||||
<InlineField label="(" labelWidth={2}>
|
||||
<Select
|
||||
placeholder={t('transformers.unary-operation-editor.placeholder-field', 'Field')}
|
||||
className="min-width-11"
|
||||
@@ -72,7 +68,6 @@ export const UnaryOperationEditor = (props: {
|
||||
onChange={onUnaryValueChanged}
|
||||
/>
|
||||
</InlineField>
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
<InlineLabel width={2}>)</InlineLabel>
|
||||
</InlineFieldRow>
|
||||
</>
|
||||
|
||||
@@ -174,7 +174,7 @@ export const ConvertFieldTypeTransformerEditor = ({
|
||||
>
|
||||
<Input
|
||||
value={c.dateFormat}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={'e.g. YYYY-MM-DD'}
|
||||
onChange={onInputFormat(idx)}
|
||||
width={24}
|
||||
@@ -193,7 +193,7 @@ export const ConvertFieldTypeTransformerEditor = ({
|
||||
>
|
||||
<Input
|
||||
value={c.joinWith}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={'JSON'}
|
||||
onChange={onJoinWithChange(idx)}
|
||||
width={16}
|
||||
@@ -211,7 +211,7 @@ export const ConvertFieldTypeTransformerEditor = ({
|
||||
>
|
||||
<Input
|
||||
value={c.dateFormat}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder={'e.g. YYYY-MM-DD'}
|
||||
onChange={onInputFormat(idx)}
|
||||
width={24}
|
||||
|
||||
@@ -81,7 +81,7 @@ export function FormatTimeTransfomerEditor({
|
||||
value={options.timeField}
|
||||
onChange={onSelectField}
|
||||
/* don't translate here as this references a field name */
|
||||
/* eslint-disable-next-line @grafana/no-untranslated-strings */
|
||||
/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */
|
||||
placeholder="time"
|
||||
isClearable
|
||||
/>
|
||||
|
||||
@@ -90,7 +90,7 @@ export function SeriesToFieldsTransformerEditor({ input, options, onChange }: Tr
|
||||
value={options.byField}
|
||||
onChange={onSelectField}
|
||||
/* don't translate here as this references a field name */
|
||||
/* eslint-disable-next-line @grafana/no-untranslated-strings */
|
||||
/* eslint-disable-next-line @grafana/i18n/no-untranslated-strings */
|
||||
placeholder="time"
|
||||
isClearable
|
||||
/>
|
||||
|
||||
@@ -118,7 +118,7 @@ export const extractFieldsTransformerEditor = ({
|
||||
{options.format === FieldExtractorID.RegExp && (
|
||||
<InlineFieldRow>
|
||||
<InlineField
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
label="RegExp"
|
||||
labelWidth={16}
|
||||
interactive={true}
|
||||
@@ -127,7 +127,7 @@ export const extractFieldsTransformerEditor = ({
|
||||
})}
|
||||
>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/(?<NewField>.*)/"
|
||||
value={options.regExp}
|
||||
onChange={onRegexpChange}
|
||||
|
||||
@@ -147,7 +147,6 @@ export function JoinByLabelsTransformerEditor({ input, options, onChange }: Prop
|
||||
{Boolean(info.addOptions.length && idx === options.join!.length - 1) && (
|
||||
<ValuePicker
|
||||
icon="plus"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
label={''}
|
||||
options={info.addOptions}
|
||||
onChange={addJoin}
|
||||
|
||||
@@ -37,7 +37,7 @@ export const intervalVariableSlice = createSlice({
|
||||
// add auto option if missing
|
||||
if (options.length && options[0].text !== 'auto') {
|
||||
options.unshift({
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
text: 'auto',
|
||||
value: '$__auto_interval_' + instanceState.name,
|
||||
selected: false,
|
||||
|
||||
@@ -87,7 +87,6 @@ export const generateLabel = (feature: FeatureLike, idx: number): string | React
|
||||
|
||||
if (first) {
|
||||
return (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
<span>
|
||||
{first}: {renderValue(props[first])}
|
||||
</span>
|
||||
@@ -98,7 +97,6 @@ export const generateLabel = (feature: FeatureLike, idx: number): string | React
|
||||
const v = props[k];
|
||||
if (isString(v)) {
|
||||
return (
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
<span>
|
||||
{k}: {renderValue(v)}
|
||||
</span>
|
||||
|
||||
+3
-3
@@ -88,7 +88,7 @@ export const AppRegistrationCredentials = (props: AppRegistrationCredentialsProp
|
||||
<Input
|
||||
aria-label={t('components.app-registration-credentials.aria-label-tenant-id', 'Tenant ID')}
|
||||
className="width-30"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.tenantId || ''}
|
||||
onChange={onTenantIdChange}
|
||||
@@ -106,7 +106,7 @@ export const AppRegistrationCredentials = (props: AppRegistrationCredentialsProp
|
||||
<Input
|
||||
className="width-30"
|
||||
aria-label={t('components.app-registration-credentials.aria-label-client-id', 'Client ID')}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.clientId || ''}
|
||||
onChange={onClientIdChange}
|
||||
@@ -150,7 +150,7 @@ export const AppRegistrationCredentials = (props: AppRegistrationCredentialsProp
|
||||
<Input
|
||||
className="width-30"
|
||||
aria-label={t('components.app-registration-credentials.aria-label-client-secret', 'Client Secret')}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.clientSecret || ''}
|
||||
onChange={onClientSecretChange}
|
||||
|
||||
@@ -154,7 +154,7 @@ export class ConfigEditor extends PureComponent<Props, State> {
|
||||
value={options.jsonData.timeout}
|
||||
type="number"
|
||||
className="width-15"
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="30"
|
||||
onChange={onTimeoutChange}
|
||||
/>
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ const AdvancedResourcePicker = ({ resources, onChange }: ResourcePickerProps<str
|
||||
id={`input-advanced-resource-picker-${index + 1}`}
|
||||
value={resource}
|
||||
onChange={(event) => onResourceChange(index, event.currentTarget.value)}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="ex: /subscriptions/$subId"
|
||||
data-testid={`input-advanced-resource-picker-${index + 1}`}
|
||||
/>
|
||||
|
||||
+4
-4
@@ -73,7 +73,7 @@ const AdvancedResourcePicker = ({ resources, onChange }: ResourcePickerProps<Azu
|
||||
id={`input-advanced-resource-picker-subscription`}
|
||||
value={resources[0]?.subscription ?? ''}
|
||||
onChange={(event) => onCommonPropChange({ subscription: event.currentTarget.value })}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX"
|
||||
/>
|
||||
</InlineField>
|
||||
@@ -91,7 +91,7 @@ const AdvancedResourcePicker = ({ resources, onChange }: ResourcePickerProps<Azu
|
||||
id={`input-advanced-resource-picker-metricNamespace`}
|
||||
value={resources[0]?.metricNamespace ?? ''}
|
||||
onChange={(event) => onCommonPropChange({ metricNamespace: event.currentTarget.value })}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="Microsoft.Insights/metricNamespaces"
|
||||
/>
|
||||
</InlineField>
|
||||
@@ -111,7 +111,7 @@ const AdvancedResourcePicker = ({ resources, onChange }: ResourcePickerProps<Azu
|
||||
id={`input-advanced-resource-picker-region`}
|
||||
value={resources[0]?.region ?? ''}
|
||||
onChange={(event) => onCommonPropChange({ region: event.currentTarget.value })}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="northeurope"
|
||||
/>
|
||||
</InlineField>
|
||||
@@ -142,7 +142,7 @@ const AdvancedResourcePicker = ({ resources, onChange }: ResourcePickerProps<Azu
|
||||
onChange={(event) =>
|
||||
onResourceChange(index, { ...resource, resourceGroup: event.currentTarget.value })
|
||||
}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="resource-group"
|
||||
/>
|
||||
<AccessoryButton
|
||||
|
||||
@@ -56,7 +56,7 @@ export function CheatSheet() {
|
||||
</li>
|
||||
</ul>
|
||||
<Trans i18nKey="cheat-sheet.macros">Macros:</Trans>
|
||||
{/* eslint-disable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable @grafana/i18n/no-untranslated-strings */}
|
||||
<ul className={styles.ulPadding}>
|
||||
<li>$__time(column) -> column AS time</li>
|
||||
<li>$__timeEpoch(column) -> DATEDIFF(second, '1970-01-01', column) AS time</li>
|
||||
@@ -84,13 +84,13 @@ export function CheatSheet() {
|
||||
<li>$__unixEpochGroup(column,'5m') -> FLOOR(column/300)*300</li>
|
||||
<li>$__unixEpochGroupAlias(column,'5m') -> FLOOR(column/300)*300 AS [time]</li>
|
||||
</ul>
|
||||
{/* eslint-enable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-enable @grafana/i18n/no-untranslated-strings */}
|
||||
<p>
|
||||
<Trans i18nKey="cheat-sheet.example-time-group" values={{ timeGroupMacro: '$__timeGroup' }}>
|
||||
Example of group by and order by with {'{{timeGroupMacro}}'}:
|
||||
</Trans>
|
||||
</p>
|
||||
{/* eslint-disable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable @grafana/i18n/no-untranslated-strings */}
|
||||
<pre>
|
||||
<code>
|
||||
SELECT $__timeGroup(date_time_col, '1h') AS time, sum(value) as value <br />
|
||||
@@ -102,11 +102,11 @@ export function CheatSheet() {
|
||||
<br />
|
||||
</code>
|
||||
</pre>
|
||||
{/* eslint-enable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-enable @grafana/i18n/no-untranslated-strings */}
|
||||
<Trans i18nKey="cheat-sheet.condtional-macros">
|
||||
Or build your own conditionals using these macros which just return the values:
|
||||
</Trans>
|
||||
{/* eslint-disable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-disable @grafana/i18n/no-untranslated-strings */}
|
||||
<ul className={styles.ulPadding}>
|
||||
<li>$__timeFrom() -> '2017-04-21T05:01:17Z'</li>
|
||||
<li>$__timeTo() -> '2017-04-21T05:01:17Z'</li>
|
||||
@@ -115,7 +115,7 @@ export function CheatSheet() {
|
||||
<li>$__unixEpochNanoFrom() -> 1494410783152415214</li>
|
||||
<li>$__unixEpochNanoTo() -> 1494497183142514872</li>
|
||||
</ul>
|
||||
{/* eslint-enable @grafana/no-untranslated-strings */}
|
||||
{/* eslint-enable @grafana/i18n/no-untranslated-strings */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
||||
>
|
||||
<Input
|
||||
width={45}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.tenantId || ''}
|
||||
onChange={onTenantIdChange}
|
||||
@@ -197,7 +197,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
||||
>
|
||||
<Input
|
||||
width={45}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.clientId || ''}
|
||||
onChange={onClientIdChange}
|
||||
@@ -242,7 +242,7 @@ export const AzureCredentialsForm = (props: Props) => {
|
||||
<Input
|
||||
width={45}
|
||||
aria-label={t('azureauth.azure-credentials-form.aria-label-client-secret', 'Client Secret')}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
|
||||
value={credentials.clientSecret || ''}
|
||||
onChange={onClientSecretChange}
|
||||
|
||||
@@ -162,7 +162,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
|
||||
name="host"
|
||||
type="text"
|
||||
value={dsSettings.url || ''}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="localhost:1433"
|
||||
onChange={onDSOptionChanged('url')}
|
||||
/>
|
||||
@@ -367,7 +367,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
|
||||
value={dsSettings.user || ''}
|
||||
placeholder={
|
||||
jsonData.authenticationType === MSSQLAuthenticationType.kerberosRaw
|
||||
? // eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
? // eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
'name@EXAMPLE.COM'
|
||||
: t('configuration.configuration-editor.placeholder-user', 'user')
|
||||
}
|
||||
@@ -434,7 +434,7 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps<Ms
|
||||
>
|
||||
<Input
|
||||
width={LONG_WIDTH}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="1m"
|
||||
value={jsonData.timeInterval || ''}
|
||||
onChange={onUpdateDatasourceJsonDataOption(props, 'timeInterval')}
|
||||
|
||||
@@ -62,7 +62,7 @@ export const KerberosConfig = (props: DataSourcePluginOptionsEditorProps<MssqlOp
|
||||
error={'Keytab file path is required'}
|
||||
>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/home/grot/grot.keytab"
|
||||
onChange={onKeytabFileChanged}
|
||||
width={LONG_WIDTH}
|
||||
@@ -85,7 +85,7 @@ export const KerberosConfig = (props: DataSourcePluginOptionsEditorProps<MssqlOp
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/tmp/krb5cc_1000"
|
||||
onChange={onCredentialCacheChanged}
|
||||
width={LONG_WIDTH}
|
||||
@@ -124,7 +124,7 @@ export const KerberosConfig = (props: DataSourcePluginOptionsEditorProps<MssqlOp
|
||||
)}
|
||||
>
|
||||
<Input
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="/home/grot/cache.json"
|
||||
onChange={onCredentialCacheFileChanged}
|
||||
width={LONG_WIDTH}
|
||||
@@ -179,7 +179,7 @@ export const KerberosAdvancedSettings = (props: DataSourcePluginOptionsEditorPro
|
||||
<Input
|
||||
type="text"
|
||||
width={LONG_WIDTH}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="0"
|
||||
defaultValue={jsonData.UDPConnectionLimit}
|
||||
onChange={(e) => {
|
||||
@@ -207,7 +207,7 @@ export const KerberosAdvancedSettings = (props: DataSourcePluginOptionsEditorPro
|
||||
<Input
|
||||
type="text"
|
||||
width={LONG_WIDTH}
|
||||
// eslint-disable-next-line @grafana/no-untranslated-strings
|
||||
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
|
||||
placeholder="true"
|
||||
defaultValue={jsonData.enableDNSLookupKDC}
|
||||
onChange={onDNSLookupKDCChanged}
|
||||
|
||||
@@ -5798,6 +5798,7 @@
|
||||
},
|
||||
"explore": {
|
||||
"accordian-logs": {
|
||||
"events": "Events",
|
||||
"footer": "Event timestamps are relative to the start time of the full trace."
|
||||
},
|
||||
"accordian-references": {
|
||||
|
||||
@@ -127,8 +127,6 @@ export const Page = () => {
|
||||
persistAuthorization={false}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
||||
{!url?.value && <div>...{/** TODO, we can make an api docs loading page here */}</div>}
|
||||
</NamespaceContext.Provider>
|
||||
</ThemeProvider>
|
||||
|
||||
Reference in New Issue
Block a user