Add more i18n keys

This commit is contained in:
ZhaiSoul 2025-03-03 23:10:17 +08:00
parent f73281c554
commit 65ebd3a4f6
10 changed files with 156 additions and 47 deletions

View File

@ -137,12 +137,16 @@
"ui.time.s": "s",
"ui.time.second": "{{time}} seconds",
"ui.unit.speed.mph": "mph",
"ui.unit.speed.kph": "kph",
"ui.time.formattedTimestamp": "%b %-d, %I:%M:%S %p",
"ui.time.formattedTimestamp.24hour": "%b %-d, %H:%M:%S",
"ui.time.formattedTimestampExcludeSeconds": "%b %-d, %I:%M %p",
"ui.time.formattedTimestampExcludeSeconds.24hour": "%b %-d, %H:%M",
"ui.time.formattedTimestampWithYear": "%b %-d %Y, %I:%M %p",
"ui.time.formattedTimestampWithYear.24hour": "%b %-d %Y, %H:%M",
"ui.time.formattedTimestampOnlyMonthAndDay": "%b %-d",
"ui.iconPicker.selectIcon": "Select an icon",
"ui.iconPicker.search.placeholder": "Search for an icon...",
@ -286,13 +290,31 @@
"ui.cameraGroup.icon": "Icon",
"ui.cameraGroup.success": "Camera group ({{name}}) has been saved.",
"ui.cameraGroup.toast.error": "Failed to save config changes: {{error}}",
"ui.cameraGroup.camera.setting": "{{cameraName}} Streaming Settings",
"ui.cameraGroup.camera.setting.desc": "Change the live streaming options for this camera group's dashboard. <em>These settings are device/browser-specific.</em>",
"ui.cameraGroup.camera.setting.audioIsAvailable": "Audio is available for this stream",
"ui.cameraGroup.camera.setting.audioIsUnavailable": "Audio is available for this stream",
"ui.cameraGroup.camera.setting.audio.tips": "Audio must be output from your camera and configured in go2rtc for this stream.",
"ui.cameraGroup.camera.setting.audio.tips.document": "Read the documentation ",
"ui.cameraGroup.camera.setting.streamMethod": "Streaming Method",
"ui.cameraGroup.camera.setting.streamMethod.method.noStreaming": "No Streaming",
"ui.cameraGroup.camera.setting.streamMethod.method.noStreaming.desc": "Camera images will only update once per minute and no live streaming will occur.",
"ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming": "Smart Streaming (recommended)",
"ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming.desc": "Smart streaming will update your camera image once per minute when no detectable activity is occurring to conserve bandwidth and resources. When activity is detected, the image seamlessly switches to a live stream.",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming": "Continuous Streaming",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc": "Camera image will always be a live stream when visible on the dashboard, even if no activity is being detected.",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc.warning": "Continuous streaming may cause high bandwidth usage and performance issues. Use with caution.",
"ui.cameraGroup.camera.setting.compatibilityMode": "Compatibility mode",
"ui.cameraGroup.camera.setting.compatibilityMode.desc": "Enable this option only if your camera's live stream is displaying color artifacts and has a diagonal line on the right side of the image.",
"ui.eventView.alerts": "Alerts",
"ui.eventView.detections": "Detections",
"ui.eventView.motion": "Motion",
"ui.eventView.motion.only": "Motion only",
"ui.eventView.allCameras": "All Cameras",
"ui.eventView.empty.alert": "There are no alerts to review",
"ui.eventView.empty.detection": "There are no detections to review",
"ui.eventView.empty.motion": "No motion data found",
"ui.exploreView.trackedObjectDetails": "Tracked Object Details",
"ui.exploreView.type.details": "details",
@ -301,6 +323,8 @@
"ui.exploreView.type.object_lifecycle": "object lifecycle",
"ui.exploreView.details.label": "Label",
"ui.exploreView.details.editSubLable": "Edit sub label",
"ui.exploreView.details.editSubLable.desc": "Enter a new sub label for this {{label}}",
"ui.exploreView.details.editSubLable.desc.noLabel": "Enter a new sub label for this tracked object",
"ui.exploreView.details.topScore": "Top Score",
"ui.exploreView.details.topScore.info": "The top score is the highest median score for the tracked object, so this may differ from the score shown on the search result thumbnail.",
"ui.exploreView.details.estimatedSpeed": "Estimated Speed",
@ -342,6 +366,7 @@
"ui.filter.subLabels": "Sub Labels",
"ui.filter.allSubLabels": "All Sub Labels",
"ui.filter.score": "Score",
"ui.filter.estimatedSpeed": "Estimated Speed ({{unit}})",
"ui.filter.features": "Features",
"ui.filter.features.hasSnapshot": "Has a snapshot",
"ui.filter.features.hasVideoClip": "Has a video clip",
@ -377,6 +402,7 @@
"ui.yes": "Yes",
"ui.no": "No",
"ui.download": "Download",
"ui.info": "Info",
"ui.live.documentTitle": "Live - Frigate",
"ui.live.documentTitle.withCamera": "{{camera}} - Live - Frigate",
@ -581,6 +607,10 @@
"ui.settingView.debug.regions": "Regions",
"ui.settingView.debug.regions.desc": "Show a box of the region of interest sent to the object detector",
"ui.settingView.debug.regions.tips": "<p className=\"mb-2\"><strong>Region Boxes</strong></p><br><p>Bright green boxes will be overlaid on areas of interest in the frame that are being sent to the object detector.</p>",
"ui.settingView.debug.objectShapeFilterDrawing": "Object Shape Filter Drawing",
"ui.settingView.debug.objectShapeFilterDrawing.desc": "Draw a rectangle on the image to view area and ratio details",
"ui.settingView.debug.objectShapeFilterDrawing.tips": "Enable this option to draw a rectangle on the camera image to show its area and ratio. These values can then be used to set object shape filter parameters in your config.",
"ui.settingView.debug.objectShapeFilterDrawing.document": "Read the documentation ",
"ui.settingView.users": "Users",
"ui.settingView.users.addUser": "Add User",

View File

@ -143,6 +143,10 @@
"ui.time.formattedTimestampExcludeSeconds.24hour": "%m月%-d日 %H:%M",
"ui.time.formattedTimestampWithYear": "%Y年%m月%-d日 %I:%M:%S %p",
"ui.time.formattedTimestampWithYear.24hour": "%Y年%m月%-d日 %H:%M",
"ui.time.formattedTimestampOnlyMonthAndDay": "%m月%-d日",
"ui.unit.speed.mph": "公里/小时",
"ui.unit.speed.kph": "英里/小时",
"ui.iconPicker.selectIcon": "选择图标",
"ui.iconPicker.search.placeholder": "搜索图标...",
@ -288,13 +292,30 @@
"ui.cameraGroup.icon": "图标",
"ui.cameraGroup.toast.success": "摄像头组({{name}})保存成功。",
"ui.cameraGroup.toast.error": "保存设置失败: {{error}}",
"ui.cameraGroup.camera.setting": "{{cameraName}} 视频流设置",
"ui.cameraGroup.camera.setting.desc": "更改此摄像头组仪表板的实时视频流选项。<em>这些设置特定于设备/浏览器。</em>",
"ui.cameraGroup.camera.setting.audioIsAvailable": "此视频流支持音频",
"ui.cameraGroup.camera.setting.audioIsUnavailable": "此视频流不支持音频",
"ui.cameraGroup.camera.setting.streamMethod": "视频流方法",
"ui.cameraGroup.camera.setting.streamMethod.method.noStreaming": "无视频流",
"ui.cameraGroup.camera.setting.streamMethod.method.noStreaming.desc": "摄像头图像每分钟仅更新一次,不会进行实时视频流播放。",
"ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming": "智能视频流(推荐)",
"ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming.desc": "智能视频流在没有检测到活动时,每分钟更新一次摄像头图像,以节省带宽和资源。当检测到活动时,图像会无缝切换到实时视频流。",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming": "持续视频流",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc": "当摄像头画面在仪表板上可见时,始终为实时视频流,即使未检测到活动。",
"ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc.warning": "持续视频流可能会导致高带宽使用和性能问题,请谨慎使用。",
"ui.cameraGroup.camera.setting.compatibilityMode": "兼容模式",
"ui.cameraGroup.camera.setting.compatibilityMode.desc": "仅在摄像头的实时视频流显示颜色伪影,并且图像右侧有一条对角线时启用此选项。",
"ui.eventView.alerts": "警告",
"ui.eventView.detections": "检测",
"ui.eventView.motion": "运动",
"ui.eventView.motion.only": "仅运动画面",
"ui.eventView.allCameras": "所有摄像头",
"ui.eventView.empty.alert": "还没有“警告”类回放",
"ui.eventView.empty.detection": "还没有“探测”类回放",
"ui.eventView.empty.motion": "还没有运动类数据",
"ui.exploreView.trackedObjectDetails": "探测对象详情",
"ui.exploreView.type.details": "详情",
@ -303,6 +324,8 @@
"ui.exploreView.type.object_lifecycle": "对象生命周期",
"ui.exploreView.details.label": "标签",
"ui.exploreView.details.editSubLable": "编辑子标签",
"ui.exploreView.details.editSubLable.desc": "为 {{label}} 输入新的子标签",
"ui.exploreView.details.editSubLable.desc.noLabel": "为此跟踪对象输入新的子标签",
"ui.exploreView.details.topScore": "最高得分",
"ui.exploreView.details.topScore.info": "最高分是跟踪对象的最高中位数得分,因此可能与搜索结果缩略图上显示的得分不同。",
"ui.exploreView.details.estimatedSpeed": "预计速度",
@ -344,6 +367,7 @@
"ui.filter.subLabels": "子标签",
"ui.filter.allSubLabels": "所有子标签",
"ui.filter.score": "分值",
"ui.filter.estimatedSpeed": "预计速度({{unit}}",
"ui.filter.features": "特性",
"ui.filter.features.hasSnapshot": "包含快照",
"ui.filter.features.hasVideoClip": "包含视频片段",
@ -582,6 +606,10 @@
"ui.settingView.debug.regions": "范围",
"ui.settingView.debug.regions.desc": "显示发送到运动检测器感兴趣范围的框。",
"ui.settingView.debug.regions.tips": "<p className=\"mb-2\"><strong>范围框</strong></p><br><p>将在帧中发送到目标检测器的感兴趣范围上叠加绿色框。</p>",
"ui.settingView.debug.objectShapeFilterDrawing": "允许绘制“对象形状过滤器”",
"ui.settingView.debug.objectShapeFilterDrawing.desc": "在图像上绘制矩形,以查看区域和比例详细信息。",
"ui.settingView.debug.objectShapeFilterDrawing.tips": "启用此选项,能够在摄像头图像上绘制矩形,将显示其区域和比例。然后,您可以使用这些值在配置中设置对象形状过滤器参数。",
"ui.settingView.debug.objectShapeFilterDrawing.document": "阅读文档(英文)",
"ui.settingView.users": "用户管理",
"ui.settingView.users.addUser": "添加用户",

View File

@ -100,7 +100,7 @@ export function CalendarRangeFilterButton({
const selectedDate = useFormattedRange(
range?.from == undefined ? 0 : range.from.getTime() / 1000 + 1,
range?.to == undefined ? 0 : range.to.getTime() / 1000 - 1,
"%b %-d",
t("ui.time.formattedTimestampOnlyMonthAndDay"),
);
const trigger = (

View File

@ -610,7 +610,7 @@ function ShowMotionOnlyButton({
className="mx-2 cursor-pointer text-primary"
htmlFor="collapse-motion"
>
Motion only
<Trans>ui.eventView.motion.only</Trans>
</Label>
</div>

View File

@ -725,7 +725,13 @@ function ObjectDetailsTab({
open={isSubLabelDialogOpen}
setOpen={setIsSubLabelDialogOpen}
title={t("ui.exploreView.details.editSubLable")}
description={`Enter a new sub label for this ${search.label ?? "tracked object"}.`}
description={
search.label
? t("ui.exploreView.details.editSubLable.desc", {
label: t(`object.${search.label}`),
})
: t("ui.exploreView.details.editSubLable.desc.noLabel")
}
onSave={handleSubLabelSave}
defaultValue={search?.sub_label || ""}
allowEmpty={true}

View File

@ -34,6 +34,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Trans } from "react-i18next";
import { t } from "i18next";
type SearchFilterDialogProps = {
config?: FrigateConfig;
@ -558,7 +559,16 @@ export function SpeedFilterContent({
<div className="overflow-x-hidden">
<DropdownMenuSeparator className="mb-3" />
<div className="mb-3 text-lg">
Estimated Speed ({config?.ui.unit_system == "metric" ? "kph" : "mph"})
<Trans
values={{
unit:
config?.ui.unit_system == "metric"
? t("ui.unit.speed.kph")
: t("ui.unit.speed.mph"),
}}
>
ui.filter.estimatedSpeed
</Trans>
</div>
<div className="flex items-center gap-1">
<Input

View File

@ -12,6 +12,7 @@ import { Input } from "@/components/ui/input";
import { zodResolver } from "@hookform/resolvers/zod";
import { useCallback, useEffect } from "react";
import { useForm } from "react-hook-form";
import { Trans } from "react-i18next";
import { z } from "zod";
type TextEntryDialogProps = {
@ -87,10 +88,10 @@ export default function TextEntryDialog({
/>
<DialogFooter className="pt-4">
<Button type="button" onClick={() => setOpen(false)}>
Cancel
<Trans>ui.cancel</Trans>
</Button>
<Button variant="select" type="submit">
Save
<Trans>ui.save</Trans>
</Button>
</DialogFooter>
</form>

View File

@ -168,11 +168,12 @@ export function CameraStreamingDialog({
<DialogContent className="sm:max-w-[425px]">
<DialogHeader className="mb-4">
<DialogTitle className="capitalize">
{camera.replaceAll("_", " ")} Streaming Settings
<Trans values={{ cameraName: camera.replaceAll("_", " ") }}>
ui.cameraGroup.camera.setting
</Trans>
</DialogTitle>
<DialogDescription>
Change the live streaming options for this camera group's dashboard.{" "}
<em>These settings are device/browser-specific.</em>
<Trans>ui.cameraGroup.camera.setting.desc</Trans>
</DialogDescription>
</DialogHeader>
<div className="flex flex-col space-y-8">
@ -235,22 +236,33 @@ export function CameraStreamingDialog({
{supportsAudioOutput ? (
<>
<LuCheck className="size-4 text-success" />
<div>Audio is available for this stream</div>
<div>
<Trans>
ui.cameraGroup.camera.setting.audioIsAvailable
</Trans>
</div>
</>
) : (
<>
<LuX className="size-4 text-danger" />
<div>Audio is unavailable for this stream</div>
<div>
<Trans>
ui.cameraGroup.camera.setting.audioIsUnavailable
</Trans>
</div>
<Popover>
<PopoverTrigger asChild>
<div className="cursor-pointer p-0">
<LuInfo className="size-4" />
<span className="sr-only">Info</span>
<span className="sr-only">
<Trans>ui.info</Trans>
</span>
</div>
</PopoverTrigger>
<PopoverContent className="w-80 text-xs">
Audio must be output from your camera and configured
in go2rtc for this stream.
<Trans>
ui.cameraGroup.camera.setting.audio.desc
</Trans>
<div className="mt-2 flex items-center text-primary">
<Link
to="https://docs.frigate.video/configuration/live"
@ -258,7 +270,9 @@ export function CameraStreamingDialog({
rel="noopener noreferrer"
className="inline"
>
Read the documentation{" "}
<Trans>
ui.cameraGroup.camera.setting.audio.desc.document
</Trans>
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
@ -272,7 +286,7 @@ export function CameraStreamingDialog({
)}
<div className="flex flex-col items-start gap-2">
<Label htmlFor="streaming-method" className="text-right">
Streaming Method
<Trans>ui.cameraGroup.camera.setting.streamMethod</Trans>
</Label>
<Select
value={streamType}
@ -282,38 +296,50 @@ export function CameraStreamingDialog({
<SelectValue placeholder="Choose a streaming option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="no-streaming">No Streaming</SelectItem>
<SelectItem value="smart">
Smart Streaming (recommended)
<SelectItem value="no-streaming">
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.noStreaming
</Trans>
</SelectItem>
<SelectItem value="smart">
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming
</Trans>
</SelectItem>
<SelectItem value="continuous">
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming
</Trans>
</SelectItem>
<SelectItem value="continuous">Continuous Streaming</SelectItem>
</SelectContent>
</Select>
{streamType === "no-streaming" && (
<p className="text-sm text-muted-foreground">
Camera images will only update once per minute and no live
streaming will occur.
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.noStreaming.desc
</Trans>
</p>
)}
{streamType === "smart" && (
<p className="text-sm text-muted-foreground">
Smart streaming will update your camera image once per minute when
no detectable activity is occurring to conserve bandwidth and
resources. When activity is detected, the image seamlessly
switches to a live stream.
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.smartStreaming.desc
</Trans>
</p>
)}
{streamType === "continuous" && (
<>
<p className="text-sm text-muted-foreground">
Camera image will always be a live stream when visible on the
dashboard, even if no activity is being detected.
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc
</Trans>
</p>
<div className="flex items-center gap-2">
<IoIosWarning className="mr-2 size-5 text-danger" />
<div className="max-w-[85%] text-sm">
Continuous streaming may cause high bandwidth usage and
performance issues. Use with caution.
<Trans>
ui.cameraGroup.camera.setting.streamMethod.method.continuousStreaming.desc.warning
</Trans>
</div>
</div>
</>
@ -331,14 +357,14 @@ export function CameraStreamingDialog({
htmlFor="compatibility"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Compatibility mode
<Trans>ui.cameraGroup.camera.setting.compatibilityMode</Trans>
</Label>
</div>
<div className="flex flex-col gap-2 leading-none">
<p className="text-sm text-muted-foreground">
Enable this option only if your camera's live stream is displaying
color artifacts and has a diagonal line on the right side of the
image.
<Trans>
ui.cameraGroup.camera.setting.compatibilityMode.desc
</Trans>
</p>
</div>
</div>
@ -350,7 +376,7 @@ export function CameraStreamingDialog({
aria-label="Cancel"
onClick={handleCancel}
>
Cancel
<Trans>ui.cancel</Trans>
</Button>
<Button
variant="select"
@ -362,10 +388,12 @@ export function CameraStreamingDialog({
{isLoading ? (
<div className="flex flex-row items-center gap-2">
<ActivityIndicator />
<span>Saving...</span>
<span>
<Trans>ui.saving</Trans>
</span>
</div>
) : (
"Save"
<Trans>ui.save</Trans>
)}
</Button>
</div>

View File

@ -348,7 +348,9 @@ export default function EventView({
) : (
<>
<MdCircle className="size-2 text-severity_significant_motion md:mr-[10px]" />
<div className="hidden md:block">Motion</div>
<div className="hidden md:block">
<Trans>ui.eventView.motion</Trans>
</div>
</>
)}
</ToggleGroupItem>
@ -1050,7 +1052,7 @@ function MotionReview({
return (
<div className="absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center justify-center text-center">
<LuFolderX className="size-16" />
No motion data found
<Trans>ui.eventView.empty.motion</Trans>
</div>
);
}

View File

@ -254,7 +254,9 @@ export default function ObjectSettingsView({
className="mb-0 cursor-pointer capitalize text-primary"
htmlFor="debugdraw"
>
Object Shape Filter Drawing
<Trans>
ui.settingView.debug.objectShapeFilterDrawing
</Trans>
</Label>
<Popover>
@ -265,10 +267,9 @@ export default function ObjectSettingsView({
</div>
</PopoverTrigger>
<PopoverContent className="w-80 text-sm">
Enable this option to draw a rectangle on the
camera image to show its area and ratio. These
values can then be used to set object shape filter
parameters in your config.
<Trans>
ui.settingView.debug.objectShapeFilterDrawing.tips
</Trans>
<div className="mt-2 flex items-center text-primary">
<Link
to="https://docs.frigate.video/configuration/object_filters#object-shape"
@ -276,7 +277,9 @@ export default function ObjectSettingsView({
rel="noopener noreferrer"
className="inline"
>
Read the documentation{" "}
<Trans>
ui.settingView.debug.objectShapeFilterDrawing.document
</Trans>
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
@ -284,8 +287,9 @@ export default function ObjectSettingsView({
</Popover>
</div>
<div className="mt-1 text-xs text-muted-foreground">
Draw a rectangle on the image to view area and ratio
details
<Trans>
ui.settingView.debug.objectShapeFilterDrawing.desc
</Trans>
</div>
</div>
<Switch