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: {
name: 'Playlist name',
interval: 'Playlist interval',
itemDelete: 'Delete playlist item',
itemDelete: 'data-testid playlist-form-delete-item',
},
BrowseDashboards: {
table: {

View File

@ -4,6 +4,7 @@ import { useAsync } from 'react-use';
import { NavModelItem } from '@grafana/data';
import { locationService } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page';
import { t, Trans } from 'app/core/internationalization';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import { PlaylistForm } from './PlaylistForm';
@ -25,16 +26,22 @@ export const PlaylistEditPage = ({ match }: Props) => {
};
const pageNav: NavModelItem = {
text: 'Edit playlist',
subTitle:
'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.',
text: t('playlist-edit.title', 'Edit playlist'),
subTitle: t(
'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 (
<Page navId="dashboards/playlists" pageNav={pageNav}>
<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} />}
</Page.Contents>
</Page>

View File

@ -5,6 +5,7 @@ import { config } from '@grafana/runtime';
import { Button, Field, Form, HorizontalGroup, Input, LinkButton } from '@grafana/ui';
import { DashboardPicker } from 'app/core/components/Select/DashboardPicker';
import { TagFilter } from 'app/core/components/TagFilter/TagFilter';
import { Trans, t } from 'app/core/internationalization';
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;
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
type="text"
{...register('name', { required: 'Name is required' })}
placeholder="Name"
{...register('name', { required: t('playlist-edit.form.name-required', 'Name is required') })}
placeholder={t('playlist-edit.form.name-placeholder', 'Name')}
defaultValue={name}
aria-label={selectors.pages.PlaylistForm.name}
/>
</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
type="text"
{...register('interval', { required: 'Interval is required' })}
placeholder="5m"
{...register('interval', {
required: t('playlist-edit.form.interval-required', 'Interval is required'),
})}
placeholder={t('playlist-edit.form.interval-placeholder', '5m')}
defaultValue={interval ?? '5m'}
aria-label={selectors.pages.PlaylistForm.interval}
/>
@ -60,20 +71,22 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
<PlaylistTable items={items} deleteItem={deleteItem} moveItem={moveItem} />
<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} />
</Field>
<Field label="Add by tag">
<Field label={t('playlist-edit.form.add-tag-label', 'Add by tag')}>
<TagFilter
isClearable
tags={[]}
hideValues
tagOptions={tagOptions}
onChange={addByTag}
placeholder="Select a tag"
placeholder={t('playlist-edit.form.add-tag-placeholder', 'Select a tag')}
/>
</Field>
</div>
@ -85,10 +98,10 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
disabled={isDisabled}
icon={saving ? 'fa fa-spinner' : undefined}
>
Save
<Trans i18nKey="playlist-edit.form.save">Save</Trans>
</Button>
<LinkButton variant="secondary" href={`${config.appSubUrl}/playlists`}>
Cancel
<Trans i18nKey="playlist-edit.form.cancel">Cancel</Trans>
</LinkButton>
</HorizontalGroup>
</>

View File

@ -1,6 +1,8 @@
import React from 'react';
import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';
import { Trans } from 'app/core/internationalization';
import { PlaylistTableRows } from './PlaylistTableRows';
import { PlaylistItem } from './types';
@ -19,7 +21,9 @@ export const PlaylistTable = ({ items, deleteItem, moveItem }: Props) => {
return (
<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}>
<Droppable droppableId="playlist-list" direction="vertical">

View File

@ -7,6 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Icon, IconButton, useStyles2, Spinner, IconName } from '@grafana/ui';
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
import { t, Trans } from 'app/core/internationalization';
import { PlaylistItem } from './types';
@ -20,7 +21,9 @@ export const PlaylistTableRows = ({ items, onDelete }: Props) => {
if (!items?.length) {
return (
<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>
);
}
@ -80,9 +83,14 @@ export const PlaylistTableRows = ({ items, onDelete }: Props) => {
name="times"
size="md"
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>
)}

View File

@ -608,6 +608,29 @@
"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": {
"aria-label": {
"choose-interval": "Automatische Aktualisierung ausgeschaltet. Aktualisierungszeitintervall auswählen",

View File

@ -608,6 +608,29 @@
"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": {
"aria-label": {
"choose-interval": "Auto refresh turned off. Choose refresh time interval",

View File

@ -613,6 +613,29 @@
"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": {
"aria-label": {
"choose-interval": "Actualización automática desactivada. Elija un intervalo de tiempo de actualización",

View File

@ -613,6 +613,29 @@
"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": {
"aria-label": {
"choose-interval": "Actualisation automatique désactivée. Choisir un intervalle de temps d'actualisation",

View File

@ -608,6 +608,29 @@
"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": {
"aria-label": {
"choose-interval": "Åūŧő řęƒřęşĥ ŧūřʼnęđ őƒƒ. Cĥőőşę řęƒřęşĥ ŧįmę įʼnŧęřväľ",

View File

@ -603,6 +603,29 @@
"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": {
"aria-label": {
"choose-interval": "自动刷新已关闭。选择刷新时间间隔",