Add events translations

This commit is contained in:
Nick Mowen 2022-08-27 11:06:50 -06:00
parent 388e80ce8d
commit 47f36693c3
2 changed files with 56 additions and 29 deletions

View File

@ -1,21 +1,46 @@
{ {
"all": "All",
"all_cameras": "All Cameras",
"all_labels": "All Labels",
"all_sub_labels": "All Sub Labels"
"all_zones": "All Zones",
"are_you_sure": "Are you sure?", "are_you_sure": "Are you sure?",
"auto_dark_mode": "Auto Dark Mode", "auto_dark_mode": "Auto Dark Mode",
"best_image": "Best Image",
"birdseye": "Birdseye", "birdseye": "Birdseye",
"cameras": "Cameras", "cameras": "Cameras",
"cancel": "Cancel", "cancel": "Cancel",
"clip": "Clip",
"close": "Close",
"_confidence": "confidence",
"custom_range": "Custom Range",
"dark": "Dark", "dark": "Dark",
"debug": "Debug", "debug": "Debug",
"delete": "Delete",
"desc_delete_saved_event": "Confirm deletion of saved event.",
"desc_no_recordings": "Make sure you have enabled the record role in your configuration for the {camera} camera.",
"documentation": "Documentation", "documentation": "Documentation",
"download_clip": "Download Clip",
"download_snapshot": "Download Snapshot",
"events": "Events", "events": "Events",
"github": "GitHub", "github": "GitHub",
"in_progress": "In Progress",
"last_month": "Last Month",
"last_seven_days": "Last Seven Days",
"light": "Light", "light": "Light",
"title_no_recordings": "No Recordings Found",
"desc_no_recordings": "Make sure you have enabled the record role in your configuration for the {camera} camera.",
"recordings": "Recordings", "recordings": "Recordings",
"restart_frigate": "Restart Frigate", "restart_frigate": "Restart Frigate",
"restart_in_progress": "Restart in progress", "restart_in_progress": "Restart in progress",
"send_to_frigate_plus": "Send To Frigate+",
"sent_to_frigate_plus": "Sent To Frigate+",
"style_guide": "Style Guide", "style_guide": "Style Guide",
"this_month": "This Month",
"thumbnail": "Thumbnail",
"title_delete_saved_event": "Delete Saved Event?",
"title_no_recordings": "No Recordings Found",
"today": "Today",
"uploading": "Uploading...",
"wait_for_restart": "Please wait a few seconds for the restart to complete before reloading the page.", "wait_for_restart": "Please wait a few seconds for the restart to complete before reloading the page.",
"yes": "Yes" "yes": "Yes",
"yesterday": "Yesterday"
} }

View File

@ -21,6 +21,7 @@ import CalendarIcon from '../icons/Calendar';
import Calendar from '../components/Calendar'; import Calendar from '../components/Calendar';
import Button from '../components/Button'; import Button from '../components/Button';
import Dialog from '../components/Dialog'; import Dialog from '../components/Dialog';
import { useTranslation } from 'react-i18next';
const API_LIMIT = 25; const API_LIMIT = 25;
@ -37,6 +38,7 @@ const monthsAgo = (num) => {
}; };
export default function Events({ path, ...props }) { export default function Events({ path, ...props }) {
const { t } = useTranslation();
const apiHost = useApiHost(); const apiHost = useApiHost();
const [searchParams, setSearchParams] = useState({ const [searchParams, setSearchParams] = useState({
before: null, before: null,
@ -241,14 +243,14 @@ export default function Events({ path, ...props }) {
return ( return (
<div className="space-y-4 p-2 px-4 w-full"> <div className="space-y-4 p-2 px-4 w-full">
<Heading>Events</Heading> <Heading>{t('events')}</Heading>
<div className="flex flex-wrap gap-2 items-center"> <div className="flex flex-wrap gap-2 items-center">
<select <select
className="basis-1/5 cursor-pointer rounded dark:bg-slate-800" className="basis-1/5 cursor-pointer rounded dark:bg-slate-800"
value={searchParams.camera} value={searchParams.camera}
onChange={(e) => onFilter('camera', e.target.value)} onChange={(e) => onFilter('camera', e.target.value)}
> >
<option value="all">all cameras</option> <option value="all">{t('all_cameras')}</option>
{filterValues.cameras.map((item) => ( {filterValues.cameras.map((item) => (
<option key={item} value={item}> <option key={item} value={item}>
{item.replaceAll('_', ' ')} {item.replaceAll('_', ' ')}
@ -260,7 +262,7 @@ export default function Events({ path, ...props }) {
value={searchParams.label} value={searchParams.label}
onChange={(e) => onFilter('label', e.target.value)} onChange={(e) => onFilter('label', e.target.value)}
> >
<option value="all">all labels</option> <option value="all">{t('all_labels')}</option>
{filterValues.labels.map((item) => ( {filterValues.labels.map((item) => (
<option key={item.replaceAll('_', ' ')} value={item}> <option key={item.replaceAll('_', ' ')} value={item}>
{item} {item}
@ -272,7 +274,7 @@ export default function Events({ path, ...props }) {
value={searchParams.zone} value={searchParams.zone}
onChange={(e) => onFilter('zone', e.target.value)} onChange={(e) => onFilter('zone', e.target.value)}
> >
<option value="all">all zones</option> <option value="all">{t('all_zones')}</option>
{filterValues.zones.map((item) => ( {filterValues.zones.map((item) => (
<option key={item} value={item}> <option key={item} value={item}>
{item.replaceAll('_', ' ')} {item.replaceAll('_', ' ')}
@ -286,7 +288,7 @@ export default function Events({ path, ...props }) {
value={searchParams.sub_label} value={searchParams.sub_label}
onChange={(e) => onFilter('sub_label', e.target.value)} onChange={(e) => onFilter('sub_label', e.target.value)}
> >
<option value="all">all sub labels</option> <option value="all">{t('all_sub_labels')}</option>
{filterValues.sub_labels.map((item) => ( {filterValues.sub_labels.map((item) => (
<option key={item} value={item}> <option key={item} value={item}>
{item} {item}
@ -306,7 +308,7 @@ export default function Events({ path, ...props }) {
{downloadEvent.has_snapshot && ( {downloadEvent.has_snapshot && (
<MenuItem <MenuItem
icon={Snapshot} icon={Snapshot}
label="Download Snapshot" label={t('download_snapshot')}
value="snapshot" value="snapshot"
href={`${apiHost}/api/events/${downloadEvent.id}/snapshot.jpg?download=true`} href={`${apiHost}/api/events/${downloadEvent.id}/snapshot.jpg?download=true`}
download download
@ -315,7 +317,7 @@ export default function Events({ path, ...props }) {
{downloadEvent.has_clip && ( {downloadEvent.has_clip && (
<MenuItem <MenuItem
icon={Clip} icon={Clip}
label="Download Clip" label={t('download_clip')}
value="clip" value="clip"
href={`${apiHost}/api/events/${downloadEvent.id}/clip.mp4?download=true`} href={`${apiHost}/api/events/${downloadEvent.id}/clip.mp4?download=true`}
download download
@ -324,7 +326,7 @@ export default function Events({ path, ...props }) {
{downloadEvent.has_snapshot && !downloadEvent.plus_id && ( {downloadEvent.has_snapshot && !downloadEvent.plus_id && (
<MenuItem <MenuItem
icon={UploadPlus} icon={UploadPlus}
label={uploading.includes(downloadEvent.id) ? 'Uploading...' : 'Send to Frigate+'} label={uploading.includes(downloadEvent.id) ? t('uploading') : t('send_to_frigate_plus')}
value="plus" value="plus"
onSelect={() => onSendToPlus(downloadEvent.id)} onSelect={() => onSendToPlus(downloadEvent.id)}
/> />
@ -332,7 +334,7 @@ export default function Events({ path, ...props }) {
{downloadEvent.plus_id && ( {downloadEvent.plus_id && (
<MenuItem <MenuItem
icon={UploadPlus} icon={UploadPlus}
label={'Sent to Frigate+'} label={t('send_to_frigate_plus')}
value="plus" value="plus"
onSelect={() => setState({ ...state, showDownloadMenu: false })} onSelect={() => setState({ ...state, showDownloadMenu: false })}
/> />
@ -345,22 +347,22 @@ export default function Events({ path, ...props }) {
onDismiss={() => setState({ ...state, setShowDatePicker: false })} onDismiss={() => setState({ ...state, setShowDatePicker: false })}
relativeTo={datePicker} relativeTo={datePicker}
> >
<MenuItem label="All" value={{ before: null, after: null }} onSelect={handleSelectDateRange} /> <MenuItem label={t('all')} value={{ before: null, after: null }} onSelect={handleSelectDateRange} />
<MenuItem label="Today" value={{ before: null, after: daysAgo(0) }} onSelect={handleSelectDateRange} /> <MenuItem label={t('today')} value={{ before: null, after: daysAgo(0) }} onSelect={handleSelectDateRange} />
<MenuItem <MenuItem
label="Yesterday" label={t('yesterday')}
value={{ before: daysAgo(0), after: daysAgo(1) }} value={{ before: daysAgo(0), after: daysAgo(1) }}
onSelect={handleSelectDateRange} onSelect={handleSelectDateRange}
/> />
<MenuItem label="Last 7 Days" value={{ before: null, after: daysAgo(7) }} onSelect={handleSelectDateRange} /> <MenuItem label={t('last_seven_days')} value={{ before: null, after: daysAgo(7) }} onSelect={handleSelectDateRange} />
<MenuItem label="This Month" value={{ before: null, after: monthsAgo(0) }} onSelect={handleSelectDateRange} /> <MenuItem label={t('this_month')} value={{ before: null, after: monthsAgo(0) }} onSelect={handleSelectDateRange} />
<MenuItem <MenuItem
label="Last Month" label={t('last_month')}
value={{ before: monthsAgo(0), after: monthsAgo(1) }} value={{ before: monthsAgo(0), after: monthsAgo(1) }}
onSelect={handleSelectDateRange} onSelect={handleSelectDateRange}
/> />
<MenuItem <MenuItem
label="Custom Range" label={t('custom_range')}
value="custom" value="custom"
onSelect={() => { onSelect={() => {
setState({ ...state, showCalendar: true, showDatePicker: false }); setState({ ...state, showCalendar: true, showDatePicker: false });
@ -397,7 +399,7 @@ export default function Events({ path, ...props }) {
</div> </div>
<div className="p-2 flex justify-start flex-row-reverse space-x-2"> <div className="p-2 flex justify-start flex-row-reverse space-x-2">
<Button className="ml-2" onClick={() => setState({ ...state, showPlusConfig: false })} type="text"> <Button className="ml-2" onClick={() => setState({ ...state, showPlusConfig: false })} type="text">
Close {t('close')}
</Button> </Button>
</div> </div>
</Dialog> </Dialog>
@ -405,12 +407,12 @@ export default function Events({ path, ...props }) {
{deleteFavoriteState.showDeleteFavorite && ( {deleteFavoriteState.showDeleteFavorite && (
<Dialog> <Dialog>
<div className="p-4"> <div className="p-4">
<Heading size="lg">Delete Saved Event?</Heading> <Heading size="lg">{t('title_delete_saved_event')}</Heading>
<p className="mb-2">Confirm deletion of saved event.</p> <p className="mb-2">{t('desc_delete_saved_event')}</p>
</div> </div>
<div className="p-2 flex justify-start flex-row-reverse space-x-2"> <div className="p-2 flex justify-start flex-row-reverse space-x-2">
<Button className="ml-2" color="red" onClick={(e) => { setDeleteFavoriteState({ ...state, showDeleteFavorite: false }); onDelete(e, deleteFavoriteState.deletingFavoriteEventId, false) }} type="text"> <Button className="ml-2" color="red" onClick={(e) => { setDeleteFavoriteState({ ...state, showDeleteFavorite: false }); onDelete(e, deleteFavoriteState.deletingFavoriteEventId, false) }} type="text">
Delete {t('delete')}
</Button> </Button>
</div> </div>
</Dialog> </Dialog>
@ -441,7 +443,7 @@ export default function Events({ path, ...props }) {
/> />
{event.end_time ? null : ( {event.end_time ? null : (
<div className="bg-slate-300 dark:bg-slate-700 absolute bottom-0 text-center w-full uppercase text-sm rounded-bl"> <div className="bg-slate-300 dark:bg-slate-700 absolute bottom-0 text-center w-full uppercase text-sm rounded-bl">
In progress {t('in_progress')}
</div> </div>
)} )}
</div> </div>
@ -468,14 +470,14 @@ export default function Events({ path, ...props }) {
{event.has_snapshot && ( {event.has_snapshot && (
<Fragment> <Fragment>
{event.plus_id ? ( {event.plus_id ? (
<div className="uppercase text-xs">Sent to Frigate+</div> <div className="uppercase text-xs">{t('sent_to_frigate_plus')}</div>
) : ( ) : (
<Button <Button
color="gray" color="gray"
disabled={uploading.includes(event.id)} disabled={uploading.includes(event.id)}
onClick={(e) => onSendToPlus(event.id, e)} onClick={(e) => onSendToPlus(event.id, e)}
> >
{uploading.includes(event.id) ? 'Uploading...' : 'Send to Frigate+'} {uploading.includes(event.id) ? t('uploading') : t('send_to_frigate_plus')}
</Button> </Button>
)} )}
</Fragment> </Fragment>
@ -497,7 +499,7 @@ export default function Events({ path, ...props }) {
<div className="mx-auto max-w-7xl"> <div className="mx-auto max-w-7xl">
{event.has_clip ? ( {event.has_clip ? (
<> <>
<Heading size="lg">Clip</Heading> <Heading size="lg">{t('clip')}</Heading>
<VideoPlayer <VideoPlayer
options={{ options={{
preload: 'auto', preload: 'auto',
@ -516,7 +518,7 @@ export default function Events({ path, ...props }) {
) : ( ) : (
<div className="flex justify-center"> <div className="flex justify-center">
<div> <div>
<Heading size="sm">{event.has_snapshot ? 'Best Image' : 'Thumbnail'}</Heading> <Heading size="sm">{event.has_snapshot ? t('best_image') : t('thumbnail')}</Heading>
<img <img
className="flex-grow-0" className="flex-grow-0"
src={ src={
@ -524,7 +526,7 @@ export default function Events({ path, ...props }) {
? `${apiHost}/api/events/${event.id}/snapshot.jpg` ? `${apiHost}/api/events/${event.id}/snapshot.jpg`
: `data:image/jpeg;base64,${event.thumbnail}` : `data:image/jpeg;base64,${event.thumbnail}`
} }
alt={`${event.label} at ${(event.top_score * 100).toFixed(0)}% confidence`} alt={`${event.label} at ${(event.top_score * 100).toFixed(0)}% ${t('_confidence')}`}
/> />
</div> </div>
</div> </div>