I18n: Migrate to I18next (#55845)

* Switch from lingui from i18next

* Change lingui messages to i18next messages

* Change lingui messages to i18next messages (grafana-ui)

* Init i18n for tests
This commit is contained in:
Josh Hunt
2022-10-06 16:34:04 +01:00
committed by GitHub
parent c1d6df4eb7
commit 5361efc225
58 changed files with 2557 additions and 4364 deletions

View File

@@ -1,4 +1,3 @@
import { t, Trans } from '@lingui/macro';
import React, { FC, ReactNode } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { useLocation } from 'react-router-dom';
@@ -20,6 +19,7 @@ import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbarSep
import config from 'app/core/config';
import { useGrafana } from 'app/core/context/GrafanaContext';
import { useBusEvent } from 'app/core/hooks/useBusEvent';
import { t, Trans } from 'app/core/internationalization';
import { DashboardCommentsModal } from 'app/features/dashboard/components/DashboardComments/DashboardCommentsModal';
import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
import { ShareModal } from 'app/features/dashboard/components/ShareModal';
@@ -139,8 +139,8 @@ export const DashNav = React.memo<Props>((props) => {
if (canStar) {
let desc = isStarred
? t({ id: 'dashboard.toolbar.unmark-favorite', message: 'Unmark as favorite' })
: t({ id: 'dashboard.toolbar.mark-favorite', message: 'Mark as favorite' });
? t('dashboard.toolbar.unmark-favorite', 'Unmark as favorite')
: t('dashboard.toolbar.mark-favorite', 'Mark as favorite');
buttons.push(
<DashNavButton
tooltip={desc}
@@ -158,7 +158,7 @@ export const DashNav = React.memo<Props>((props) => {
<ModalsController key="button-share">
{({ showModal, hideModal }) => (
<DashNavButton
tooltip={t({ id: 'dashboard.toolbar.share', message: 'Share dashboard or panel' })}
tooltip={t('dashboard.toolbar.share', 'Share dashboard or panel')}
icon="share-alt"
iconSize="lg"
onClick={() => {
@@ -184,7 +184,7 @@ export const DashNav = React.memo<Props>((props) => {
<ModalsController key="button-dashboard-comments">
{({ showModal, hideModal }) => (
<DashNavButton
tooltip={t({ id: 'dashboard.toolbar.comments-show', message: 'Show dashboard comments' })}
tooltip={t('dashboard.toolbar.comments-show', 'Show dashboard comments')}
icon="comment-alt-message"
iconSize="lg"
onClick={() => {
@@ -207,16 +207,16 @@ export const DashNav = React.memo<Props>((props) => {
return (
<ButtonGroup key="playlist-buttons">
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.playlist-previous', message: 'Go to previous dashboard' })}
tooltip={t('dashboard.toolbar.playlist-previous', 'Go to previous dashboard')}
icon="backward"
onClick={onPlaylistPrev}
narrow
/>
<ToolbarButton onClick={onPlaylistStop}>
<Trans id="dashboard.toolbar.playlist-stop">Stop playlist</Trans>
<Trans i18nKey="dashboard.toolbar.playlist-stop">Stop playlist</Trans>
</ToolbarButton>
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.playlist-next', message: 'Go to next dashboard' })}
tooltip={t('dashboard.toolbar.playlist-next', 'Go to next dashboard')}
icon="forward"
onClick={onPlaylistNext}
narrow
@@ -245,7 +245,7 @@ export const DashNav = React.memo<Props>((props) => {
const buttons: ReactNode[] = [];
const tvButton = config.featureToggles.topnav ? null : (
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.tv-button', message: 'Cycle view mode' })}
tooltip={t('dashboard.toolbar.tv-button', 'Cycle view mode')}
icon="monitor"
onClick={onToggleTVMode}
key="tv-button"
@@ -263,7 +263,7 @@ export const DashNav = React.memo<Props>((props) => {
if (canEdit && !isFullscreen) {
buttons.push(
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.add-panel', message: 'Add panel' })}
tooltip={t('dashboard.toolbar.add-panel', 'Add panel')}
icon="panel-add"
onClick={onAddPanel}
key="button-panel-add"
@@ -276,7 +276,7 @@ export const DashNav = React.memo<Props>((props) => {
<ModalsController key="button-save">
{({ showModal, hideModal }) => (
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.save', message: 'Save dashboard' })}
tooltip={t('dashboard.toolbar.save', 'Save dashboard')}
icon="save"
onClick={() => {
showModal(SaveDashboardDrawer, {
@@ -293,7 +293,7 @@ export const DashNav = React.memo<Props>((props) => {
if (snapshotUrl) {
buttons.push(
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.open-original', message: 'Open original dashboard' })}
tooltip={t('dashboard.toolbar.open-original', 'Open original dashboard')}
onClick={() => gotoSnapshotOrigin(snapshotUrl)}
icon="link"
key="button-snapshot"
@@ -304,7 +304,7 @@ export const DashNav = React.memo<Props>((props) => {
if (showSettings) {
buttons.push(
<ToolbarButton
tooltip={t({ id: 'dashboard.toolbar.settings', message: 'Dashboard settings' })}
tooltip={t('dashboard.toolbar.settings', 'Dashboard settings')}
icon="cog"
onClick={onOpenSettings}
key="button-settings"

View File

@@ -1,4 +1,3 @@
import { t } from '@lingui/macro';
import React, { Component } from 'react';
import { Unsubscribable } from 'rxjs';
@@ -7,6 +6,7 @@ import { TimeRangeUpdatedEvent } from '@grafana/runtime';
import { defaultIntervals, RefreshPicker } from '@grafana/ui';
import { TimePickerWithHistory } from 'app/core/components/TimePicker/TimePickerWithHistory';
import { appEvents } from 'app/core/core';
import { t } from 'app/core/internationalization';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { ShiftTimeEvent, ShiftTimeEventDirection, ZoomOutEvent } from '../../../../types/events';
@@ -107,20 +107,20 @@ export class DashNavTimeControls extends Component<Props> {
value={dashboard.refresh}
intervals={intervals}
isOnCanvas={isOnCanvas}
tooltip={t({ id: 'dashboard.toolbar.refresh', message: 'Refresh dashboard' })}
tooltip={t('dashboard.toolbar.refresh', 'Refresh dashboard')}
noIntervalPicker={hideIntervalPicker}
offDescriptionAriaLabelMsg={t({
id: 'dashboard.refresh-picker.off-description',
message: 'Auto refresh turned off. Choose refresh time interval',
})}
offDescriptionAriaLabelMsg={t(
'dashboard.refresh-picker.off-description',
'Auto refresh turned off. Choose refresh time interval'
)}
onDescriptionAriaLabelMsg={(durationAriaLabel) =>
t({
id: 'dashboard.refresh-picker.on-description',
message: `Choose refresh time interval with current interval ${durationAriaLabel} selected`,
})
t(
'dashboard.refresh-picker.on-description',
`Choose refresh time interval with current interval ${durationAriaLabel} selected`
)
}
offOptionLabelMsg={t({ id: 'dashboard.refresh-picker.off-label', message: 'Off' })}
offOptionAriaLabelMsg={t({ id: 'dashboard.refresh-picker.off-arialabel', message: 'Turn off auto refresh' })}
offOptionLabelMsg={t('dashboard.refresh-picker.off-label', 'Off')}
offOptionAriaLabelMsg={t('dashboard.refresh-picker.off-arialabel', 'Turn off auto refresh')}
/>
</>
);

View File

@@ -1,9 +1,9 @@
import { t } from '@lingui/macro';
import React, { useState } from 'react';
import { CoreApp, DataSourceApi, formattedValueToString, getValueFormat, PanelData, PanelPlugin } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { Drawer, Tab, TabsBar } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { InspectDataTab } from 'app/features/inspector/InspectDataTab';
import { InspectErrorTab } from 'app/features/inspector/InspectErrorTab';
import { InspectJSONTab } from 'app/features/inspector/InspectJSONTab';
@@ -59,10 +59,7 @@ export const InspectContent = ({
}
const panelTitle = getTemplateSrv().replace(panel.title, panel.scopedVars, 'text') || 'Panel';
const title = t({
id: 'dashboard.inspect.title',
message: `Inspect: ${panelTitle}`,
});
const title = t('dashboard.inspect.title', 'Inspect: {{panelTitle}}', { panelTitle });
return (
<Drawer
@@ -74,13 +71,13 @@ export const InspectContent = ({
scrollableContent
tabs={
<TabsBar>
{tabs.map((t, index) => {
{tabs.map((tab, index) => {
return (
<Tab
key={`${t.value}-${index}`}
label={t.label}
active={t.value === activeTab}
onChangeTab={() => setCurrentTab(t.value || InspectTab.Data)}
key={`${tab.value}-${index}`}
label={tab.label}
active={tab.value === activeTab}
onChangeTab={() => setCurrentTab(tab.value || InspectTab.Data)}
/>
);
})}
@@ -124,8 +121,9 @@ function formatStats(data: PanelData) {
const requestTime = request.endTime ? request.endTime - request.startTime : 0;
const formatted = formattedValueToString(getValueFormat('ms')(requestTime));
return t({
id: 'dashboard.inspect.subtitle',
message: `${queryCount} queries with total query time of ${formatted}`,
});
return (
<Trans i18nKey="dashboard.inspect.subtitle">
{{ queryCount }} queries with total query time of {{ formatted }}
</Trans>
);
}

View File

@@ -1,9 +1,9 @@
import { t } from '@lingui/macro';
import { useMemo } from 'react';
import useAsync from 'react-use/lib/useAsync';
import { DataQueryError, DataSourceApi, PanelData, PanelPlugin } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { t } from 'app/core/internationalization';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { InspectTab } from 'app/features/inspector/types';
@@ -48,18 +48,18 @@ export const useInspectTabs = (
return useMemo(() => {
const tabs = [];
if (supportsDataQuery(plugin)) {
tabs.push({ label: t({ id: 'dashboard.inspect.data-tab', message: 'Data' }), value: InspectTab.Data });
tabs.push({ label: t({ id: 'dashboard.inspect.stats-tab', message: 'Stats' }), value: InspectTab.Stats });
tabs.push({ label: t('dashboard.inspect.data-tab', 'Data'), value: InspectTab.Data });
tabs.push({ label: t('dashboard.inspect.stats-tab', 'Stats'), value: InspectTab.Stats });
}
if (metaDs) {
tabs.push({ label: t({ id: 'dashboard.inspect.meta-tab', message: 'Meta Data' }), value: InspectTab.Meta });
tabs.push({ label: t('dashboard.inspect.meta-tab', 'Meta Data'), value: InspectTab.Meta });
}
tabs.push({ label: t({ id: 'dashboard.inspect.json-tab', message: 'JSON' }), value: InspectTab.JSON });
tabs.push({ label: t('dashboard.inspect.json-tab', 'JSON'), value: InspectTab.JSON });
if (error && error.message) {
tabs.push({ label: t({ id: 'dashboard.inspect.error-tab', message: 'Error' }), value: InspectTab.Error });
tabs.push({ label: t('dashboard.inspect.error-tab', 'Error'), value: InspectTab.Error });
}
// This is a quick internal hack to allow custom actions in inspect
@@ -67,13 +67,13 @@ export const useInspectTabs = (
const supplier = (window as any).grafanaPanelInspectActionSupplier as PanelInspectActionSupplier;
if (supplier && supplier.getActions(panel)?.length) {
tabs.push({
label: t({ id: 'dashboard.inspect.actions-tab', message: 'Actions' }),
label: t('dashboard.inspect.actions-tab', 'Actions'),
value: InspectTab.Actions,
});
}
if (dashboard.meta.canEdit && supportsDataQuery(plugin)) {
tabs.push({ label: t({ id: 'dashboard.inspect.query-tab', message: 'Query' }), value: InspectTab.Query });
tabs.push({ label: t('dashboard.inspect.query-tab', 'Query'), value: InspectTab.Query });
}
return tabs;
}, [panel, plugin, metaDs, dashboard, error]);

View File

@@ -1,8 +1,8 @@
import { t, Trans } from '@lingui/macro';
import React, { FormEvent, PureComponent } from 'react';
import { reportInteraction } from '@grafana/runtime/src';
import { ClipboardButton, Field, Modal, Switch, TextArea } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { ThemePicker } from './ThemePicker';
import { ShareModalTabProps } from './types';
@@ -65,21 +65,18 @@ export class ShareEmbed extends PureComponent<Props, State> {
const isRelativeTime = this.props.dashboard ? this.props.dashboard.time.to === 'now' : false;
const timeRangeDescription = isRelativeTime
? t({
id: 'share-modal.embed.time-range-description',
message: 'Transforms the current relative time range to an absolute time range',
})
? t(
'share-modal.embed.time-range-description',
'Transforms the current relative time range to an absolute time range'
)
: '';
return (
<>
<p className="share-modal-info-text">
<Trans id="share-modal.embed.info">Generate HTML for embedding an iframe with this panel.</Trans>
<Trans i18nKey="share-modal.embed.info">Generate HTML for embedding an iframe with this panel.</Trans>
</p>
<Field
label={t({ id: 'share-modal.embed.time-range', message: 'Current time range' })}
description={timeRangeDescription}
>
<Field label={t('share-modal.embed.time-range', 'Current time range')} description={timeRangeDescription}>
<Switch
id="share-current-time-range"
value={useCurrentTimeRange}
@@ -88,13 +85,11 @@ export class ShareEmbed extends PureComponent<Props, State> {
</Field>
<ThemePicker selectedTheme={selectedTheme} onChange={this.onThemeChange} />
<Field
label={t({ id: 'share-modal.embed.html', message: 'Embed HTML' })}
description={
<Trans id="share-modal.embed.html-description">
The HTML code below can be pasted and included in another web page. Unless anonymous access is enabled,
the user viewing that page need to be signed into Grafana for the graph to load.
</Trans>
}
label={t('share-modal.embed.html', 'Embed HTML')}
description={t(
'share-modal.embed.html-description',
'The HTML code below can be pasted and included in another web page. Unless anonymous access is enabled, the user viewing that page need to be signed into Grafana for the graph to load.'
)}
>
<TextArea
data-testid="share-embed-html"
@@ -106,7 +101,7 @@ export class ShareEmbed extends PureComponent<Props, State> {
</Field>
<Modal.ButtonRow>
<ClipboardButton icon="copy" variant="primary" getText={this.getIframeHtml}>
<Trans id="share-modal.embed.copy">Copy to clipboard</Trans>
<Trans i18nKey="share-modal.embed.copy">Copy to clipboard</Trans>
</ClipboardButton>
</Modal.ButtonRow>
</>

View File

@@ -1,10 +1,10 @@
import { Trans, t } from '@lingui/macro';
import { saveAs } from 'file-saver';
import React, { PureComponent } from 'react';
import { config, reportInteraction } from '@grafana/runtime';
import { Button, Field, Modal, Switch } from '@grafana/ui';
import { appEvents } from 'app/core/core';
import { t, Trans } from 'app/core/internationalization';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { DashboardExporter } from 'app/features/dashboard/components/DashExportModal';
import { ShowModalReactEvent } from 'app/types/events';
@@ -135,20 +135,14 @@ export class ShareExport extends PureComponent<Props, State> {
const { shareExternally } = this.state;
const { trimDefaults } = this.state;
const exportExternallyTranslation = t({
id: 'share-modal.export.share-externally-label',
message: `Export for sharing externally`,
});
const exportExternallyTranslation = t('share-modal.export.share-externally-label', `Export for sharing externally`);
const exportDefaultTranslation = t({
id: 'share-modal.export.share-default-label',
message: `Export with default values removed`,
});
const exportDefaultTranslation = t('share-modal.export.share-default-label', `Export with default values removed`);
return (
<>
<p className="share-modal-info-text">
<Trans id="share-modal.export.info-text">Export this dashboard.</Trans>
<Trans i18nKey="share-modal.export.info-text">Export this dashboard.</Trans>
</p>
<Field label={exportExternallyTranslation}>
<Switch id="share-externally-toggle" value={shareExternally} onChange={this.onShareExternallyChange} />
@@ -160,13 +154,13 @@ export class ShareExport extends PureComponent<Props, State> {
)}
<Modal.ButtonRow>
<Button variant="secondary" onClick={onDismiss} fill="outline">
<Trans id="share-modal.export.cancel-button">Cancel</Trans>
<Trans i18nKey="share-modal.export.cancel-button">Cancel</Trans>
</Button>
<Button variant="secondary" onClick={this.onViewJson}>
<Trans id="share-modal.export.view-button">View JSON</Trans>
<Trans i18nKey="share-modal.export.view-button">View JSON</Trans>
</Button>
<Button variant="primary" onClick={this.onSaveAsFile}>
<Trans id="share-modal.export.save-button">Save to file</Trans>
<Trans i18nKey="share-modal.export.save-button">Save to file</Trans>
</Button>
</Modal.ButtonRow>
</>

View File

@@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro';
import React, { useEffect } from 'react';
import { reportInteraction } from '@grafana/runtime/src';
import { Trans } from 'app/core/internationalization';
import { AddLibraryPanelContents } from 'app/features/library-panels/components/AddLibraryPanelModal/AddLibraryPanelModal';
import { ShareModalTabProps } from './types';
@@ -22,7 +22,7 @@ export const ShareLibraryPanel = ({ panel, initialFolderId, onDismiss }: Props)
return (
<>
<p className="share-modal-info-text">
<Trans id="share-modal.library.info">Create library panel.</Trans>
<Trans i18nKey="share-modal.library.info">Create library panel.</Trans>
</p>
<AddLibraryPanelContents panel={panel} initialFolderId={initialFolderId} onDismiss={onDismiss!} />
</>

View File

@@ -1,10 +1,10 @@
import { Trans, t } from '@lingui/macro';
import React, { PureComponent } from 'react';
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
import { reportInteraction } from '@grafana/runtime/src';
import { Alert, ClipboardButton, Field, FieldSet, Icon, Input, Switch } from '@grafana/ui';
import config from 'app/core/config';
import { t, Trans } from 'app/core/internationalization';
import { ThemePicker } from './ThemePicker';
import { ShareModalTabProps } from './types';
@@ -81,30 +81,21 @@ export class ShareLink extends PureComponent<Props, State> {
const selectors = e2eSelectors.pages.SharePanelModal;
const isDashboardSaved = Boolean(dashboard.id);
const timeRangeLabelTranslation = t({
id: 'share-modal.link.time-range-label',
message: `Lock time range`,
});
const timeRangeLabelTranslation = t('share-modal.link.time-range-label', `Lock time range`);
const timeRangeDescriptionTranslation = t({
id: 'share-modal.link.time-range-description',
message: `Transforms the current relative time range to an absolute time range`,
});
const timeRangeDescriptionTranslation = t(
'share-modal.link.time-range-description',
`Transforms the current relative time range to an absolute time range`
);
const shortenURLTranslation = t({
id: 'share-modal.link.shorten-url',
message: `Shorten URL`,
});
const shortenURLTranslation = t('share-modal.link.shorten-url', `Shorten URL`);
const linkURLTranslation = t({
id: 'share-modal.link.link-url',
message: `Link URL`,
});
const linkURLTranslation = t('share-modal.link.link-url', `Link URL`);
return (
<>
<p className="share-modal-info-text">
<Trans id="share-modal.link.info-text">
<Trans i18nKey="share-modal.link.info-text">
Create a direct link to this dashboard or panel, customized with the options below.
</Trans>
</p>
@@ -128,7 +119,7 @@ export class ShareLink extends PureComponent<Props, State> {
readOnly
addonAfter={
<ClipboardButton icon="copy" variant="primary" getText={this.getShareUrl}>
<Trans id="share-modal.link.copy-link-button">Copy</Trans>
<Trans i18nKey="share-modal.link.copy-link-button">Copy</Trans>
</ClipboardButton>
}
/>
@@ -142,7 +133,7 @@ export class ShareLink extends PureComponent<Props, State> {
<a href={imageUrl} target="_blank" rel="noreferrer" aria-label={selectors.linkToRenderedImage}>
<Icon name="camera" />
&nbsp;
<Trans id="share-modal.link.rendered-image">Direct link rendered image</Trans>
<Trans i18nKey="share-modal.link.rendered-image">Direct link rendered image</Trans>
</a>
</div>
)}
@@ -150,10 +141,10 @@ export class ShareLink extends PureComponent<Props, State> {
{!isDashboardSaved && (
<Alert
severity="info"
title={t({ id: 'share-modal.link.save-alert', message: `Dashboard is not saved` })}
title={t('share-modal.link.save-alert', 'Dashboard is not saved')}
bottomSpacing={0}
>
<Trans id="share-modal.link.save-dashboard">
<Trans i18nKey="share-modal.link.save-dashboard">
To render a panel image, you must save the dashboard first.
</Trans>
</Alert>
@@ -164,10 +155,10 @@ export class ShareLink extends PureComponent<Props, State> {
{panel && !config.rendererAvailable && (
<Alert
severity="info"
title={t({ id: 'share-modal.link.render-alert', message: `Image renderer plugin not installed` })}
title={t('share-modal.link.render-alert', 'Image renderer plugin not installed')}
bottomSpacing={0}
>
<Trans id="share-modal.link.render-instructions">
<Trans i18nKey="share-modal.link.render-instructions">
To render a panel image, you must install the&nbsp;
<a
href="https://grafana.com/grafana/plugins/grafana-image-renderer"

View File

@@ -1,10 +1,10 @@
import { t } from '@lingui/macro';
import React from 'react';
import { reportInteraction } from '@grafana/runtime/src';
import { Modal, ModalTabsHeader, TabContent } from '@grafana/ui';
import { config } from 'app/core/config';
import { contextSrv } from 'app/core/core';
import { t } from 'app/core/internationalization';
import { SharePublicDashboard } from 'app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboard';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard';
@@ -38,25 +38,25 @@ function getInitialState(props: Props): State {
function getTabs(props: Props) {
const { panel } = props;
const linkLabel = t({ id: 'share-modal.tab-title.link', message: 'Link' });
const linkLabel = t('share-modal.tab-title.link', 'Link');
const tabs: ShareModalTabModel[] = [{ label: linkLabel, value: 'link', component: ShareLink }];
if (contextSrv.isSignedIn) {
const snapshotLabel = t({ id: 'share-modal.tab-title.snapshot', message: 'Snapshot' });
const snapshotLabel = t('share-modal.tab-title.snapshot', 'Snapshot');
tabs.push({ label: snapshotLabel, value: 'snapshot', component: ShareSnapshot });
}
if (panel) {
const embedLabel = t({ id: 'share-modal.tab-title.embed', message: 'Embed' });
const embedLabel = t('share-modal.tab-title.embed', 'Embed');
tabs.push({ label: embedLabel, value: 'embed', component: ShareEmbed });
if (!isPanelModelLibraryPanel(panel)) {
const libraryPanelLabel = t({ id: 'share-modal.tab-title.library-panel', message: 'Library panel' });
const libraryPanelLabel = t('share-modal.tab-title.library-panel', 'Library panel');
tabs.push({ label: libraryPanelLabel, value: 'library_panel', component: ShareLibraryPanel });
}
tabs.push(...customPanelTabs);
} else {
const exportLabel = t({ id: 'share-modal.tab-title.export', message: 'Export' });
const exportLabel = t('share-modal.tab-title.export', 'Export');
tabs.push({ label: exportLabel, value: 'export', component: ShareExport });
tabs.push(...customDashboardTabs);
}
@@ -106,15 +106,7 @@ export class ShareModal extends React.Component<Props, State> {
renderTitle() {
const { panel } = this.props;
const { activeTab } = this.state;
const title = panel
? t({
id: 'share-modal.panel.title',
message: 'Share Panel',
})
: t({
id: 'share-modal.dashboard.title',
message: 'Share',
});
const title = panel ? t('share-modal.panel.title', 'Share Panel') : t('share-modal.dashboard.title', 'Share');
const tabs = this.getTabs();
return (

View File

@@ -1,9 +1,9 @@
import { Trans, t } from '@lingui/macro';
import React, { PureComponent } from 'react';
import { SelectableValue } from '@grafana/data';
import { getBackendSrv, reportInteraction } from '@grafana/runtime';
import { Button, ClipboardButton, Field, Input, LinkButton, Modal, Select, Spinner } from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
@@ -37,31 +37,19 @@ export class ShareSnapshot extends PureComponent<Props, State> {
this.dashboard = props.dashboard;
this.expireOptions = [
{
label: t({
id: 'share-modal.snapshot.expire-never',
message: `Never`,
}),
label: t('share-modal.snapshot.expire-never', `Never`),
value: 0,
},
{
label: t({
id: 'share-modal.snapshot.expire-hour',
message: `1 Hour`,
}),
label: t('share-modal.snapshot.expire-hour', `1 Hour`),
value: 60 * 60,
},
{
label: t({
id: 'share-modal.snapshot.expire-day',
message: `1 Day`,
}),
label: t('share-modal.snapshot.expire-day', `1 Day`),
value: 60 * 60 * 24,
},
{
label: t({
id: 'share-modal.snapshot.expire-week',
message: `7 Days`,
}),
label: t('share-modal.snapshot.expire-week', `7 Days`),
value: 60 * 60 * 24 * 7,
},
];
@@ -227,39 +215,26 @@ export class ShareSnapshot extends PureComponent<Props, State> {
const { snapshotName, selectedExpireOption, timeoutSeconds, isLoading, sharingButtonText, externalEnabled } =
this.state;
const snapshotNameTranslation = t({
id: 'share-modal.snapshot.name',
message: `Snapshot name`,
});
const expireTranslation = t({
id: 'share-modal.snapshot.expire',
message: `Expire`,
});
const timeoutTranslation = t({
id: 'share-modal.snapshot.timeout',
message: `Timeout (seconds)`,
});
const timeoutDescriptionTranslation = t({
id: 'share-modal.snapshot.timeout-description',
message: `You might need to configure the timeout value if it takes a long time to collect your dashboard
metrics.`,
});
const snapshotNameTranslation = t('share-modal.snapshot.name', `Snapshot name`);
const expireTranslation = t('share-modal.snapshot.expire', `Expire`);
const timeoutTranslation = t('share-modal.snapshot.timeout', `Timeout (seconds)`);
const timeoutDescriptionTranslation = t(
'share-modal.snapshot.timeout-description',
`You might need to configure the timeout value if it takes a long time to collect your dashboard metrics.`
);
return (
<>
<div>
<p className="share-modal-info-text">
<Trans id="share-modal.snapshot.info-text-1">
<Trans i18nKey="share-modal.snapshot.info-text-1">
A snapshot is an instant way to share an interactive dashboard publicly. When created, we strip sensitive
data like queries (metric, template, and annotation) and panel links, leaving only the visible metric data
and series names embedded in your dashboard.
</Trans>
</p>
<p className="share-modal-info-text">
<Trans id="share-modal.snapshot.info-text-2">
<Trans i18nKey="share-modal.snapshot.info-text-2">
Keep in mind, your snapshot <em>can be viewed by anyone</em> that has the link and can access the URL.
Share wisely.
</Trans>
@@ -283,7 +258,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
<Modal.ButtonRow>
<Button variant="secondary" onClick={onDismiss} fill="outline">
<Trans id="share-modal.snapshot.cancel-button">Cancel</Trans>
<Trans i18nKey="share-modal.snapshot.cancel-button">Cancel</Trans>
</Button>
{externalEnabled && (
<Button variant="secondary" disabled={isLoading} onClick={this.createSnapshot(true)}>
@@ -291,7 +266,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
</Button>
)}
<Button variant="primary" disabled={isLoading} onClick={this.createSnapshot()}>
<Trans id="share-modal.snapshot.local-button">Local Snapshot</Trans>
<Trans i18nKey="share-modal.snapshot.local-button">Local Snapshot</Trans>
</Button>
</Modal.ButtonRow>
</>
@@ -310,16 +285,16 @@ export class ShareSnapshot extends PureComponent<Props, State> {
readOnly
addonAfter={
<ClipboardButton icon="copy" variant="primary" getText={this.getSnapshotUrl}>
<Trans id="share-modal.snapshot.copy-link-button">Copy</Trans>
<Trans i18nKey="share-modal.snapshot.copy-link-button">Copy</Trans>
</ClipboardButton>
}
/>
</Field>
<div className="pull-right" style={{ padding: '5px' }}>
<Trans id="share-modal.snapshot.mistake-message">Did you make a mistake? </Trans>&nbsp;
<Trans i18nKey="share-modal.snapshot.mistake-message">Did you make a mistake? </Trans>&nbsp;
<LinkButton fill="text" target="_blank" onClick={this.deleteSnapshot}>
<Trans id="share-modal.snapshot.delete-button">Delete snapshot.</Trans>
<Trans i18nKey="share-modal.snapshot.delete-button">Delete snapshot.</Trans>
</LinkButton>
</div>
</>
@@ -330,7 +305,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
return (
<div className="share-modal-header">
<p className="share-modal-info-text">
<Trans id="share-modal.snapshot.deleted-message">
<Trans i18nKey="share-modal.snapshot.deleted-message">
The snapshot has been deleted. If you have already accessed it once, then it might take up to an hour before
before it is removed from browser caches or CDN caches.
</Trans>

View File

@@ -1,8 +1,8 @@
import { t } from '@lingui/macro';
import React from 'react';
import { SelectableValue } from '@grafana/data';
import { RadioButtonGroup, Field } from '@grafana/ui';
import { t } from 'app/core/internationalization';
interface Props {
selectedTheme: string;
@@ -12,35 +12,21 @@ interface Props {
export const ThemePicker = ({ selectedTheme = 'current', onChange }: Props) => {
const themeOptions: Array<SelectableValue<string>> = [
{
label: t({
id: 'share-modal.theme-picker.current',
message: `Current`,
}),
label: t('share-modal.theme-picker.current', `Current`),
value: 'current',
},
{
label: t({
id: 'share-modal.theme-picker.dark',
message: `Dark`,
}),
label: t('share-modal.theme-picker.dark', `Dark`),
value: 'dark',
},
{
label: t({
id: 'share-modal.theme-picker.light',
message: `Light`,
}),
label: t('share-modal.theme-picker.light', `Light`),
value: 'light',
},
];
return (
<Field
label={t({
id: 'share-modal.theme-picker.field-name',
message: `Theme`,
})}
>
<Field label={t('share-modal.theme-picker.field-name', `Theme`)}>
<RadioButtonGroup options={themeOptions} value={selectedTheme} onChange={onChange} />
</Field>
);