Internationalization: Mark up PlaylistEditPage for translations (#74455)

* PlaylistEdit Page i18n

* Update public/app/features/playlist/PlaylistEditPage.tsx

Co-authored-by: Ashley Harrison <ashharrison90@gmail.com>

* Update public/app/features/playlist/PlaylistEditPage.tsx

Co-authored-by: Ashley Harrison <ashharrison90@gmail.com>

* PlaylistForm

* more changes

* PlaylistForm

* PlaylistForm

* Update public/app/features/playlist/PlaylistEditPage.tsx

Co-authored-by: Ashley Harrison <ashharrison90@gmail.com>

* Update public/app/features/playlist/PlaylistEditPage.tsx

Co-authored-by: Ashley Harrison <ashharrison90@gmail.com>

* Update PlaylistForm.tsx

* Update Add- labels

* couple of missed keys

---------

Co-authored-by: Ashley Harrison <ashharrison90@gmail.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
This commit is contained in:
Khushi Jain 2023-09-13 14:32:51 +05:30 committed by GitHub
parent 3bae1c564d
commit c1704b5ee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 192 additions and 22 deletions

View File

@ -275,7 +275,7 @@ export const Pages = {
PlaylistForm: { PlaylistForm: {
name: 'Playlist name', name: 'Playlist name',
interval: 'Playlist interval', interval: 'Playlist interval',
itemDelete: 'Delete playlist item', itemDelete: 'data-testid playlist-form-delete-item',
}, },
BrowseDashboards: { BrowseDashboards: {
table: { table: {

View File

@ -4,6 +4,7 @@ import { useAsync } from 'react-use';
import { NavModelItem } from '@grafana/data'; import { NavModelItem } from '@grafana/data';
import { locationService } from '@grafana/runtime'; import { locationService } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page'; import { Page } from 'app/core/components/Page/Page';
import { t, Trans } from 'app/core/internationalization';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { PlaylistForm } from './PlaylistForm'; import { PlaylistForm } from './PlaylistForm';
@ -25,16 +26,22 @@ export const PlaylistEditPage = ({ match }: Props) => {
}; };
const pageNav: NavModelItem = { const pageNav: NavModelItem = {
text: 'Edit playlist', text: t('playlist-edit.title', 'Edit playlist'),
subTitle: subTitle: t(
'A playlist rotates through a pre-selected list of dashboards. A playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.', 'playlist-edit.sub-title',
'A playlist rotates through a pre-selected list of dashboards. A playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.'
),
}; };
return ( return (
<Page navId="dashboards/playlists" pageNav={pageNav}> <Page navId="dashboards/playlists" pageNav={pageNav}>
<Page.Contents isLoading={playlist.loading}> <Page.Contents isLoading={playlist.loading}>
{playlist.error && <div>Error loading playlist: {JSON.stringify(playlist.error)}</div>} {playlist.error && (
<div>
<Trans i18nKey="playlist-edit.error-prefix">Error loading playlist:</Trans>
{JSON.stringify(playlist.error)}
</div>
)}
{playlist.value && <PlaylistForm onSubmit={onSubmit} playlist={playlist.value} />} {playlist.value && <PlaylistForm onSubmit={onSubmit} playlist={playlist.value} />}
</Page.Contents> </Page.Contents>
</Page> </Page>

View File

@ -5,6 +5,7 @@ import { config } from '@grafana/runtime';
import { Button, Field, Form, HorizontalGroup, Input, LinkButton } from '@grafana/ui'; import { Button, Field, Form, HorizontalGroup, Input, LinkButton } from '@grafana/ui';
import { DashboardPicker } from 'app/core/components/Select/DashboardPicker'; import { DashboardPicker } from 'app/core/components/Select/DashboardPicker';
import { TagFilter } from 'app/core/components/TagFilter/TagFilter'; import { TagFilter } from 'app/core/components/TagFilter/TagFilter';
import { Trans, t } from 'app/core/internationalization';
import { getGrafanaSearcher } from '../search/service'; import { getGrafanaSearcher } from '../search/service';
@ -38,20 +39,30 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
const isDisabled = items.length === 0 || Object.keys(errors).length > 0; const isDisabled = items.length === 0 || Object.keys(errors).length > 0;
return ( return (
<> <>
<Field label="Name" invalid={!!errors.name} error={errors?.name?.message}> <Field
label={t('playlist-edit.form.name-label', 'Name')}
invalid={!!errors.name}
error={errors?.name?.message}
>
<Input <Input
type="text" type="text"
{...register('name', { required: 'Name is required' })} {...register('name', { required: t('playlist-edit.form.name-required', 'Name is required') })}
placeholder="Name" placeholder={t('playlist-edit.form.name-placeholder', 'Name')}
defaultValue={name} defaultValue={name}
aria-label={selectors.pages.PlaylistForm.name} aria-label={selectors.pages.PlaylistForm.name}
/> />
</Field> </Field>
<Field label="Interval" invalid={!!errors.interval} error={errors?.interval?.message}> <Field
label={t('playlist-edit.form.interval-label', 'Interval')}
invalid={!!errors.interval}
error={errors?.interval?.message}
>
<Input <Input
type="text" type="text"
{...register('interval', { required: 'Interval is required' })} {...register('interval', {
placeholder="5m" required: t('playlist-edit.form.interval-required', 'Interval is required'),
})}
placeholder={t('playlist-edit.form.interval-placeholder', '5m')}
defaultValue={interval ?? '5m'} defaultValue={interval ?? '5m'}
aria-label={selectors.pages.PlaylistForm.interval} aria-label={selectors.pages.PlaylistForm.interval}
/> />
@ -60,20 +71,22 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
<PlaylistTable items={items} deleteItem={deleteItem} moveItem={moveItem} /> <PlaylistTable items={items} deleteItem={deleteItem} moveItem={moveItem} />
<div className="gf-form-group"> <div className="gf-form-group">
<h3 className="page-headering">Add dashboards</h3> <h3 className="page-headering">
<Trans i18nKey="playlist-edit.form.heading">Add dashboards</Trans>
</h3>
<Field label="Add by title"> <Field label={t('playlist-edit.form.add-title-label', 'Add by title')}>
<DashboardPicker id="dashboard-picker" onChange={addByUID} key={items.length} /> <DashboardPicker id="dashboard-picker" onChange={addByUID} key={items.length} />
</Field> </Field>
<Field label="Add by tag"> <Field label={t('playlist-edit.form.add-tag-label', 'Add by tag')}>
<TagFilter <TagFilter
isClearable isClearable
tags={[]} tags={[]}
hideValues hideValues
tagOptions={tagOptions} tagOptions={tagOptions}
onChange={addByTag} onChange={addByTag}
placeholder="Select a tag" placeholder={t('playlist-edit.form.add-tag-placeholder', 'Select a tag')}
/> />
</Field> </Field>
</div> </div>
@ -85,10 +98,10 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
disabled={isDisabled} disabled={isDisabled}
icon={saving ? 'fa fa-spinner' : undefined} icon={saving ? 'fa fa-spinner' : undefined}
> >
Save <Trans i18nKey="playlist-edit.form.save">Save</Trans>
</Button> </Button>
<LinkButton variant="secondary" href={`${config.appSubUrl}/playlists`}> <LinkButton variant="secondary" href={`${config.appSubUrl}/playlists`}>
Cancel <Trans i18nKey="playlist-edit.form.cancel">Cancel</Trans>
</LinkButton> </LinkButton>
</HorizontalGroup> </HorizontalGroup>
</> </>

View File

@ -1,6 +1,8 @@
import React from 'react'; import React from 'react';
import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd'; import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';
import { Trans } from 'app/core/internationalization';
import { PlaylistTableRows } from './PlaylistTableRows'; import { PlaylistTableRows } from './PlaylistTableRows';
import { PlaylistItem } from './types'; import { PlaylistItem } from './types';
@ -19,7 +21,9 @@ export const PlaylistTable = ({ items, deleteItem, moveItem }: Props) => {
return ( return (
<div className="gf-form-group"> <div className="gf-form-group">
<h3 className="page-headering">Dashboards</h3> <h3 className="page-headering">
<Trans i18nKey="playlist-edit.form.table-heading">Dashboards</Trans>
</h3>
<DragDropContext onDragEnd={onDragEnd}> <DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="playlist-list" direction="vertical"> <Droppable droppableId="playlist-list" direction="vertical">

View File

@ -7,6 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { Icon, IconButton, useStyles2, Spinner, IconName } from '@grafana/ui'; import { Icon, IconButton, useStyles2, Spinner, IconName } from '@grafana/ui';
import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
import { t, Trans } from 'app/core/internationalization';
import { PlaylistItem } from './types'; import { PlaylistItem } from './types';
@ -20,7 +21,9 @@ export const PlaylistTableRows = ({ items, onDelete }: Props) => {
if (!items?.length) { if (!items?.length) {
return ( return (
<div> <div>
<em>Playlist is empty. Add dashboards below.</em> <em>
<Trans i18nKey="playlist-edit.form.table-empty">Playlist is empty. Add dashboards below.</Trans>
</em>
</div> </div>
); );
} }
@ -80,9 +83,14 @@ export const PlaylistTableRows = ({ items, onDelete }: Props) => {
name="times" name="times"
size="md" size="md"
onClick={() => onDelete(index)} onClick={() => onDelete(index)}
tooltip={selectors.pages.PlaylistForm.itemDelete} data-testid={selectors.pages.PlaylistForm.itemDelete}
tooltip={t('playlist-edit.form.table-delete', 'Delete playlist item')}
/>
<Icon
title={t('playlist-edit.form.table-drag', 'Drag and drop to reorder')}
name="draggabledots"
size="md"
/> />
<Icon title="Drag and drop to reorder" name="draggabledots" size="md" />
</div> </div>
</div> </div>
)} )}

View File

@ -608,6 +608,29 @@
"view": "Anzeigen" "view": "Anzeigen"
} }
}, },
"playlist-edit": {
"error-prefix": "",
"form": {
"add-tag-label": "",
"add-tag-placeholder": "",
"add-title-label": "",
"cancel": "",
"heading": "",
"interval-label": "",
"interval-placeholder": "",
"interval-required": "",
"name-label": "",
"name-placeholder": "",
"name-required": "",
"save": "",
"table-delete": "",
"table-drag": "",
"table-empty": "",
"table-heading": ""
},
"sub-title": "",
"title": ""
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "Automatische Aktualisierung ausgeschaltet. Aktualisierungszeitintervall auswählen", "choose-interval": "Automatische Aktualisierung ausgeschaltet. Aktualisierungszeitintervall auswählen",

View File

@ -608,6 +608,29 @@
"view": "View" "view": "View"
} }
}, },
"playlist-edit": {
"error-prefix": "Error loading playlist:",
"form": {
"add-tag-label": "Add by tag",
"add-tag-placeholder": "Select a tag",
"add-title-label": "Add by title",
"cancel": "Cancel",
"heading": "Add dashboards",
"interval-label": "Interval",
"interval-placeholder": "5m",
"interval-required": "Interval is required",
"name-label": "Name",
"name-placeholder": "Name",
"name-required": "Name is required",
"save": "Save",
"table-delete": "Delete playlist item",
"table-drag": "Drag and drop to reorder",
"table-empty": "Playlist is empty. Add dashboards below.",
"table-heading": "Dashboards"
},
"sub-title": "A playlist rotates through a pre-selected list of dashboards. A playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.",
"title": "Edit playlist"
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "Auto refresh turned off. Choose refresh time interval", "choose-interval": "Auto refresh turned off. Choose refresh time interval",

View File

@ -613,6 +613,29 @@
"view": "Vista" "view": "Vista"
} }
}, },
"playlist-edit": {
"error-prefix": "",
"form": {
"add-tag-label": "",
"add-tag-placeholder": "",
"add-title-label": "",
"cancel": "",
"heading": "",
"interval-label": "",
"interval-placeholder": "",
"interval-required": "",
"name-label": "",
"name-placeholder": "",
"name-required": "",
"save": "",
"table-delete": "",
"table-drag": "",
"table-empty": "",
"table-heading": ""
},
"sub-title": "",
"title": ""
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "Actualización automática desactivada. Elija un intervalo de tiempo de actualización", "choose-interval": "Actualización automática desactivada. Elija un intervalo de tiempo de actualización",

View File

@ -613,6 +613,29 @@
"view": "Afficher" "view": "Afficher"
} }
}, },
"playlist-edit": {
"error-prefix": "",
"form": {
"add-tag-label": "",
"add-tag-placeholder": "",
"add-title-label": "",
"cancel": "",
"heading": "",
"interval-label": "",
"interval-placeholder": "",
"interval-required": "",
"name-label": "",
"name-placeholder": "",
"name-required": "",
"save": "",
"table-delete": "",
"table-drag": "",
"table-empty": "",
"table-heading": ""
},
"sub-title": "",
"title": ""
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "Actualisation automatique désactivée. Choisir un intervalle de temps d'actualisation", "choose-interval": "Actualisation automatique désactivée. Choisir un intervalle de temps d'actualisation",

View File

@ -608,6 +608,29 @@
"view": "Vįęŵ" "view": "Vįęŵ"
} }
}, },
"playlist-edit": {
"error-prefix": "Ēřřőř ľőäđįʼnģ pľäyľįşŧ:",
"form": {
"add-tag-label": "Åđđ þy ŧäģ",
"add-tag-placeholder": "Ŝęľęčŧ ä ŧäģ",
"add-title-label": "Åđđ þy ŧįŧľę",
"cancel": "Cäʼnčęľ",
"heading": "Åđđ đäşĥþőäřđş",
"interval-label": "Ĩʼnŧęřväľ",
"interval-placeholder": "5m",
"interval-required": "Ĩʼnŧęřväľ įş řęqūįřęđ",
"name-label": "Ńämę",
"name-placeholder": "Ńämę",
"name-required": "Ńämę įş řęqūįřęđ",
"save": "Ŝävę",
"table-delete": "Đęľęŧę pľäyľįşŧ įŧęm",
"table-drag": "Đřäģ äʼnđ đřőp ŧő řęőřđęř",
"table-empty": "Pľäyľįşŧ įş ęmpŧy. Åđđ đäşĥþőäřđş þęľőŵ.",
"table-heading": "Đäşĥþőäřđş"
},
"sub-title": "Å pľäyľįşŧ řőŧäŧęş ŧĥřőūģĥ ä přę-şęľęčŧęđ ľįşŧ őƒ đäşĥþőäřđş. Å pľäyľįşŧ čäʼn þę ä ģřęäŧ ŵäy ŧő þūįľđ şįŧūäŧįőʼnäľ äŵäřęʼnęşş, őř ĵūşŧ şĥőŵ őƒƒ yőūř męŧřįčş ŧő yőūř ŧęäm őř vįşįŧőřş.",
"title": "Ēđįŧ pľäyľįşŧ"
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "Åūŧő řęƒřęşĥ ŧūřʼnęđ őƒƒ. Cĥőőşę řęƒřęşĥ ŧįmę įʼnŧęřväľ", "choose-interval": "Åūŧő řęƒřęşĥ ŧūřʼnęđ őƒƒ. Cĥőőşę řęƒřęşĥ ŧįmę įʼnŧęřväľ",

View File

@ -603,6 +603,29 @@
"view": "查看" "view": "查看"
} }
}, },
"playlist-edit": {
"error-prefix": "",
"form": {
"add-tag-label": "",
"add-tag-placeholder": "",
"add-title-label": "",
"cancel": "",
"heading": "",
"interval-label": "",
"interval-placeholder": "",
"interval-required": "",
"name-label": "",
"name-placeholder": "",
"name-required": "",
"save": "",
"table-delete": "",
"table-drag": "",
"table-empty": "",
"table-heading": ""
},
"sub-title": "",
"title": ""
},
"refresh-picker": { "refresh-picker": {
"aria-label": { "aria-label": {
"choose-interval": "自动刷新已关闭。选择刷新时间间隔", "choose-interval": "自动刷新已关闭。选择刷新时间间隔",