mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-02 17:25:22 +03:00
Add events translations
This commit is contained in:
parent
388e80ce8d
commit
47f36693c3
@ -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"
|
||||||
}
|
}
|
||||||
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user