diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 69425b735..3204244a6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,12 +2,12 @@ @@ -24,7 +24,7 @@ ## Additional information - This PR fixes or closes issue: fixes # -- This PR is related to issue: +- This PR is related to issue: ## Checklist @@ -35,4 +35,5 @@ - [ ] The code change is tested and works locally. - [ ] Local tests pass. **Your PR cannot be merged unless tests pass** - [ ] There is no commented out code in this PR. +- [ ] UI changes including text have used i18n keys and have been added to the `en` locale. - [ ] The code has been formatted using Ruff (`ruff format frigate`) diff --git a/README.md b/README.md index 5b67c86c3..b15bb5c2f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ # Frigate - NVR With Realtime Object Detection for IP Cameras +\[English\] | [简体中文](https://github.com/blakeblackshear/frigate/README_CN.md) + A complete and local NVR designed for [Home Assistant](https://www.home-assistant.io) with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras. Use of a [Google Coral Accelerator](https://coral.ai/products/) is optional, but highly recommended. The Coral will outperform even the best CPUs and can process 100+ FPS with very little overhead. diff --git a/README_CN.md b/README_CN.md new file mode 100644 index 000000000..6f4b5c4ed --- /dev/null +++ b/README_CN.md @@ -0,0 +1,52 @@ +
+
+
detect stream, check error logs"
+ },
+ "cameraDisabled": "Camera is disabled",
+ "stats": {
+ "streamType": {
+ "title": "Stream Type:",
+ "short": "Type"
+ },
+ "bandwidth": {
+ "title": "Bandwidth:",
+ "short": "Bandwidth"
+ },
+ "latency": {
+ "title": "Latency:",
+ "value": "{{seconds}} seconds",
+ "short": {
+ "title": "Latency",
+ "value": "{{seconds}} sec"
+ }
+ },
+ "totalFrames": "Total Frames:",
+ "droppedFrames": {
+ "title": "Dropped Frames:",
+ "short": {
+ "title": "Dropped",
+ "value": "{{droppedFrames}} frames"
+ }
+ },
+ "decodedFrames": "Decoded Frames:",
+ "droppedFrameRate": "Dropped Frame Rate:"
+ },
+ "toast": {
+ "success": {
+ "submittedFrigatePlus": "Successfully submitted frame to Frigate+"
+ },
+ "error": {
+ "submitFrigatePlusFailed": "Failed to submit frame to Frigate+"
+ }
+ }
+}
diff --git a/web/public/locales/en/objects.json b/web/public/locales/en/objects.json
new file mode 100644
index 000000000..130bfcc53
--- /dev/null
+++ b/web/public/locales/en/objects.json
@@ -0,0 +1,120 @@
+{
+ "person": "Person",
+ "bicycle": "Bicycle",
+ "car": "Car",
+ "motorcycle": "Motorcycle",
+ "airplane": "Airplane",
+ "bus": "Bus",
+ "train": "Train",
+ "boat": "Boat",
+ "traffic_light": "Traffic Light",
+ "fire_hydrant": "Fire Hydrant",
+ "street_sign": "Street Sign",
+ "stop_sign": "Stop Sign",
+ "parking_meter": "Parking Meter",
+ "bench": "Bench",
+ "bird": "Bird",
+ "cat": "Cat",
+ "dog": "Dog",
+ "horse": "Horse",
+ "sheep": "Sheep",
+ "cow": "Cow",
+ "elephant": "Elephant",
+ "bear": "Bear",
+ "zebra": "Zebra",
+ "giraffe": "Giraffe",
+ "hat": "Hat",
+ "backpack": "Backpack",
+ "umbrella": "Umbrella",
+ "shoe": "Shoe",
+ "eye_glasses": "Eye Glasses",
+ "handbag": "Handbag",
+ "tie": "Tie",
+ "suitcase": "Suitcase",
+ "frisbee": "Frisbee",
+ "skis": "Skis",
+ "snowboard": "Snowboard",
+ "sports_ball": "Sports Ball",
+ "kite": "Kite",
+ "baseball_bat": "Baseball Bat",
+ "baseball_glove": "Baseball Glove",
+ "skateboard": "Skateboard",
+ "surfboard": "Surfboard",
+ "tennis_racket": "Tennis Racket",
+ "bottle": "Bottle",
+ "plate": "Plate",
+ "wine_glass": "Wine Glass",
+ "cup": "Cup",
+ "fork": "Fork",
+ "knife": "Knife",
+ "spoon": "Spoon",
+ "bowl": "Bowl",
+ "banana": "Banana",
+ "apple": "Apple",
+ "sandwich": "Sandwich",
+ "orange": "Orange",
+ "broccoli": "Broccoli",
+ "carrot": "Carrot",
+ "hot_dog": "Hot Dog",
+ "pizza": "Pizza",
+ "donut": "Donut",
+ "cake": "Cake",
+ "chair": "Chair",
+ "couch": "Couch",
+ "potted_plant": "Potted Plant",
+ "bed": "Bed",
+ "mirror": "Mirror",
+ "dining_table": "Dining Table",
+ "window": "Window",
+ "desk": "Desk",
+ "toilet": "Toilet",
+ "door": "Door",
+ "tv": "TV",
+ "laptop": "Laptop",
+ "mouse": "Mouse",
+ "remote": "Remote",
+ "keyboard": "Keyboard",
+ "cell_phone": "Cell Phone",
+ "microwave": "Microwave",
+ "oven": "Oven",
+ "toaster": "Toaster",
+ "sink": "Sink",
+ "refrigerator": "Refrigerator",
+ "blender": "Blender",
+ "book": "Book",
+ "clock": "Clock",
+ "vase": "Vase",
+ "scissors": "Scissors",
+ "teddy_bear": "Teddy Bear",
+ "hair_dryer": "Hair Dryer",
+ "toothbrush": "Toothbrush",
+ "hair_brush": "Hair Brush",
+ "vehicle": "Vehicle",
+ "squirrel": "Squirrel",
+ "deer": "Deer",
+ "animal": "Animal",
+ "bark": "Bark",
+ "fox": "Fox",
+ "goat": "Goat",
+ "rabbit": "Rabbit",
+ "raccoon": "Raccoon",
+ "robot_lawnmower": "Robot Lawnmower",
+ "waste_bin": "Waste Bin",
+ "on_demand": "On Demand",
+ "face": "Face",
+ "license_plate": "License Plate",
+ "package": "Package",
+ "bbq_grill": "BBQ Grill",
+ "amazon": "Amazon",
+ "usps": "USPS",
+ "ups": "UPS",
+ "fedex": "FedEx",
+ "dhl": "DHL",
+ "an_post": "An Post",
+ "purolator": "Purolator",
+ "postnl": "PostNL",
+ "nzpost": "NZPost",
+ "postnord": "PostNord",
+ "gls": "GLS",
+ "dpd": "DPD"
+}
diff --git a/web/public/locales/en/views/configEditor.json b/web/public/locales/en/views/configEditor.json
new file mode 100644
index 000000000..eca79fcba
--- /dev/null
+++ b/web/public/locales/en/views/configEditor.json
@@ -0,0 +1,16 @@
+{
+ "documentTitle": "Config Editor - Frigate",
+ "configEditor": "Config Editor",
+ "copyConfig": "Copy Config",
+ "saveAndRestart": "Save & Restart",
+ "saveOnly": "Save Only",
+ "toast": {
+ "success": {
+ "copyToClipboard": "Config copied to clipboard."
+ },
+ "error": {
+ "savingError": "Error saving config"
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/web/public/locales/en/views/events.json b/web/public/locales/en/views/events.json
new file mode 100644
index 000000000..332817b00
--- /dev/null
+++ b/web/public/locales/en/views/events.json
@@ -0,0 +1,35 @@
+{
+ "alerts": "Alerts",
+ "detections": "Detections",
+ "motion": {
+ "label": "Motion",
+ "only": "Motion only"
+ },
+ "allCameras": "All Cameras",
+ "empty": {
+ "alert": "There are no alerts to review",
+ "detection": "There are no detections to review",
+ "motion": "No motion data found"
+ },
+ "timeline": "Timeline",
+ "timeline.aria": "Select timeline",
+ "events": {
+ "label": "Events",
+ "aria": "Select events",
+ "noFoundForTimePeriod": "No events found for this time period."
+ },
+ "documentTitle": "Review - Frigate",
+ "recordings": {
+ "documentTitle": "Recordings - Frigate"
+ },
+ "calendarFilter": {
+ "last24Hours": "Last 24 Hours"
+ },
+ "markAsReviewed": "Mark as Reviewed",
+ "markTheseItemsAsReviewed": "Mark these items as reviewed",
+ "newReviewItems": {
+ "label": "View new review items",
+ "button": "New Items To Review"
+ },
+ "camera": "Camera"
+}
diff --git a/web/public/locales/en/views/explore.json b/web/public/locales/en/views/explore.json
new file mode 100644
index 000000000..2f5b5bcb1
--- /dev/null
+++ b/web/public/locales/en/views/explore.json
@@ -0,0 +1,183 @@
+{
+ "documentTitle": "Explore - Frigate",
+ "generativeAI": "Generative AI",
+ "exploreIsUnavailable": {
+ "title": "Explore is Unavailable",
+ "embeddingsReindexing": {
+ "context": "Explore can be used after tracked object embeddings have finished reindexing.",
+ "startingUp": "Starting up...",
+ "estimatedTime": "Estimated time remaining:",
+ "finishingShortly": "Finishing shortly",
+ "step": {
+ "thumbnailsEmbedded": "Thumbnails embedded: ",
+ "descriptionsEmbedded": "Descriptions embedded: ",
+ "trackedObjectsProcessed": "Tracked objects processed: "
+ }
+ },
+ "downloadingModels": {
+ "context": "Frigate is downloading the necessary embeddings models to support the Semantic Search feature. This may take several minutes depending on the speed of your network connection.",
+ "setup": {
+ "visionModel": "Vision model",
+ "visionModelFeatureExtractor": "Vision model feature extractor",
+ "textModel": "Text model",
+ "textTokenizer": "Text tokenizer"
+ },
+ "tips": {
+ "context": "You may want to reindex the embeddings of your tracked objects once the models are downloaded.",
+ "documentation": "Read the documentation"
+ },
+ "error": "An error has occurred. Check Frigate logs."
+ }
+ },
+ "trackedObjectDetails": "Tracked Object Details",
+ "type": {
+ "details": "details",
+ "snapshot": "snapshot",
+ "video": "video",
+ "object_lifecycle": "object lifecycle"
+ },
+ "objectLifecycle": {
+ "title": "Object Lifecycle",
+ "noImageFound": "No image found for this timestamp.",
+ "createObjectMask": "Create Object Mask",
+ "adjustAnnotationSettings": "Adjust annotation settings",
+ "scrollViewTips": "Scroll to view the significant moments of this object's lifecycle.",
+ "autoTrackingTips": "Bounding box positions will be inaccurate for autotracking cameras.",
+ "lifecycleItemDesc": {
+ "visible": "{{label}} detected",
+ "entered_zone": "{{label}} entered {{zones}}",
+ "active": "{{label}} became active",
+ "stationary": "{{label}} became stationary",
+ "attribute": {
+ "faceOrLicense_plate": "{{attribute}} detected for {{label}}",
+ "other": "{{label}} recognized as {{attribute}}"
+ },
+ "gone": "{{label}} left",
+ "heard": "{{label}} heard",
+ "external": "{{label}} detected"
+ },
+ "annotationSettings": {
+ "title": "Annotation Settings",
+ "showAllZones": {
+ "title": "Show All Zones",
+ "desc": "Always show zones on frames where objects have entered a zone."
+ },
+ "offset": {
+ "label": "Annotation Offset",
+ "desc": "This data comes from your camera's detect feed but is overlayed on images from the the record feed. It is unlikely that the two streams are perfectly in sync. As a result, the bounding box and the footage will not line up perfectly. However, the annotation_offset field can be used to adjust this.",
+ "documentation": "Read the documentation ",
+ "millisecondsToOffset": "Milliseconds to offset detect annotations by. Default: 0",
+ "tips": "TIP: Imagine there is an event clip with a person walking from left to right. If the event timeline bounding box is consistently to the left of the person then the value should be decreased. Similarly, if a person is walking from left to right and the bounding box is consistently ahead of the person then the value should be increased."
+ }
+ },
+ "carousel": {
+ "previous": "Previous slide",
+ "next": "Next slide"
+ }
+ },
+ "details": {
+ "item": {
+ "title": "Review Item Details",
+ "desc": "Review item details",
+ "button": {
+ "share": "Share this review item",
+ "viewInExplore": "View in Explore"
+ },
+ "tips": {
+ "mismatch_one": "{{count}} unavailable object was detected and included in this review item. Those objects either did not qualify as an alert or detection or have already been cleaned up/deleted.",
+ "mismatch_other": "{{count}} unavailable objects were detected and included in this review item. Those objects either did not qualify as an alert or detection or have already been cleaned up/deleted.",
+ "hasMissingObjects": "Adjust your configuration if you want Frigate to save tracked objects for the following labels: {{objects}}"
+ },
+ "toast": {
+ "success": {
+ "regenerate": "A new description has been requested from {{provider}}. Depending on the speed of your provider, the new description may take some time to regenerate.",
+ "updatedSublabel": "Successfully updated sub label."
+ },
+ "error": {
+ "regenerate": "Failed to call {{provider}} for a new description: {{errorMessage}}",
+ "updatedSublabelFailed": "Failed to update sub label: {{errorMessage}}"
+ }
+ }
+ },
+ "label": "Label",
+ "editSubLabel": {
+ "title": "Edit sub label",
+ "desc": "Enter a new sub label for this {{label}}",
+ "descNoLabel": "Enter a new sub label for this tracked object"
+ },
+ "topScore": {
+ "label": "Top Score",
+ "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."
+ },
+ "estimatedSpeed": "Estimated Speed",
+ "objects": "Objects",
+ "camera": "Camera",
+ "zones": "Zones",
+ "timestamp": "Timestamp",
+ "button": {
+ "findSimilar": "Find Similar",
+ "regenerate": {
+ "title": "Regenerate",
+ "label": "Regenerate tracked object description"
+ }
+ },
+ "description": {
+ "label": "Description",
+ "placeholder": "Description of the tracked object",
+ "aiTips": "Frigate will not request a description from your Generative AI provider until the tracked object's lifecycle has ended."
+ },
+ "expandRegenerationMenu": "Expand regeneration menu",
+ "regenerateFromSnapshot": "Regenerate from Snapshot",
+ "regenerateFromThumbnails": "Regenerate from Thumbnails",
+ "tips": {
+ "descriptionSaved": "Successfully saved description",
+ "saveDescriptionFailed": "Failed to update the description: {{errorMessage}}"
+ }
+ },
+ "itemMenu": {
+ "downloadVideo": {
+ "label": "Download video",
+ "aria": "Download video"
+ },
+ "downloadSnapshot": {
+ "label": "Download snapshot",
+ "aria": "Download snapshot"
+ },
+ "viewObjectLifecycle": {
+ "label": "View object lifecycle",
+ "aria": "Show the object lifecycle"
+ },
+ "findSimilar": {
+ "label": "Find similar",
+ "aria": "Find similar tracked objects"
+ },
+ "submitToPlus": {
+ "label": "Submit to Frigate+",
+ "aria": "Submit to Frigate Plus"
+ },
+ "viewInHistory": {
+ "label": "View in History",
+ "aria": "View in History"
+ },
+ "deleteTrackedObject": {
+ "label": "Delete this tracked object"
+ }
+ },
+ "dialog": {
+ "confirmDelete": {
+ "title": "Confirm Delete",
+ "desc": "Deleting this tracked object removes the snapshot, any saved embeddings, and any associated object lifecycle entries. Recorded footage of this tracked object in History view will NOT be deleted.mode: {{effectiveRetainMode}}, so this on-demand recording will only keep segments with {{effectiveRetainModeName}}."
+ },
+ "editLayout": {
+ "label": "Edit Layout",
+ "group": {
+ "label": "Edit Camera Group"
+ },
+ "exitEdit": "Exit Editing"
+ }
+}
diff --git a/web/public/locales/en/views/recording.json b/web/public/locales/en/views/recording.json
new file mode 100644
index 000000000..9033d7819
--- /dev/null
+++ b/web/public/locales/en/views/recording.json
@@ -0,0 +1,12 @@
+{
+ "export": "Export",
+ "calendar": "Calendar",
+ "filter": "Filter",
+ "filters": "Filters",
+ "toast": {
+ "error": {
+ "noValidTimeSelected": "No valid time range selected",
+ "endTimeMustAfterStartTime": "End time must be after start time"
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/public/locales/en/views/search.json b/web/public/locales/en/views/search.json
new file mode 100644
index 000000000..8d8e878a8
--- /dev/null
+++ b/web/public/locales/en/views/search.json
@@ -0,0 +1,67 @@
+{
+ "search": "Search",
+ "savedSearches": "Saved Searches",
+ "searchFor": "Search for {{inputValue}}",
+ "button": {
+ "clear": "Clear search",
+ "save": "Save search",
+ "delete": "Delete saved search",
+ "filterInformation": "Filter information",
+ "filterActive": "Filters active"
+ },
+ "trackedObjectId": "Tracked Object ID",
+ "filter": {
+ "label": {
+ "cameras": "Cameras",
+ "labels": "Labels",
+ "zones": "Zones",
+ "sub_labels": "Sub Labels",
+ "search_type": "Search Type",
+ "time_range": "Time Range",
+ "before": "Before",
+ "after": "After",
+ "min_score": "Min Score",
+ "max_score": "Max Score",
+ "min_speed": "Min Speed",
+ "max_speed": "Max Speed",
+ "recognized_license_plate": "Recognized License Plate",
+ "has_clip": "Has Clip",
+ "has_snapshot": "Has Snapshot"
+ },
+ "searchType": {
+ "thumbnail": "Thumbnail",
+ "description": "Description"
+ },
+ "toast": {
+ "error": {
+ "beforeDateBeLaterAfter": "The 'before' date must be later than the 'after' date.",
+ "afterDatebeEarlierBefore": "The 'after' date must be earlier than the 'before' date.",
+ "minScoreMustBeLessOrEqualMaxScore": "The 'min_score' must be less than or equal to the 'max_score'.",
+ "maxScoreMustBeGreaterOrEqualMinScore": "The 'max_score' must be greater than or equal to the 'min_score'.",
+ "minSpeedMustBeLessOrEqualMaxSpeed": "The 'min_speed' must be less than or equal to the 'max_speed'.",
+ "maxSpeedMustBeGreaterOrEqualMinSpeed": "The 'max_speed' must be greater than or equal to the 'min_speed'."
+ }
+ },
+ "tips": {
+ "title": "How to use text filters",
+ "desc": {
+ "text": "Filters help you narrow down your search results. Here's how to use them in the input field:",
+ "step": "cameras:front_door label:person before:01012024 time_range:3:00PM-4:00PM "
+ }
+ },
+ "header": {
+ "currentFilterType": "Filter Values",
+ "noFilters": "Filters",
+ "activeFilters": "Active Filters"
+ }
+ },
+ "similaritySearch": {
+ "title": "Similarity Search",
+ "active": "Similarity search active",
+ "clear": "Clear similarity search"
+ },
+ "placeholder": {
+ "search": "Search..."
+ }
+}
diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json
new file mode 100644
index 000000000..ed9d291a1
--- /dev/null
+++ b/web/public/locales/en/views/settings.json
@@ -0,0 +1,553 @@
+{
+ "documentTitle": {
+ "default": "Settings - Frigate",
+ "authentication": "Authentication Settings - Frigate",
+ "camera": "Camera Settings - Frigate",
+ "classification": "Classification Settings - Frigate",
+ "masksAndZones": "Mask and Zone Editor - Frigate",
+ "motionTuner": "Motion Tuner - Frigate",
+ "object": "Object Settings - Frigate",
+ "general": "General Settings - Frigate",
+ "frigatePlus": "Frigate+ Settings - Frigate"
+ },
+ "menu": {
+ "uiSettings": "UI Settings",
+ "classificationSettings": "Classification Settings",
+ "cameraSettings": "Camera Settings",
+ "masksAndZones": "Masks / Zones",
+ "motionTuner": "Motion Tuner",
+ "debug": "Debug",
+ "users": "Users",
+ "notifications": "Notifications",
+ "frigateplus": "Frigate+"
+ },
+ "dialog": {
+ "unsavedChanges": {
+ "title": "You have unsaved changes.",
+ "desc": "Do you want to save your changes before continuing?"
+ }
+ },
+ "cameraSetting": {
+ "camera": "Camera",
+ "noCamera": "No Camera"
+ },
+ "general": {
+ "title": "General Settings",
+ "liveDashboard": {
+ "title": "Live Dashboard",
+ "automaticLiveView": {
+ "label": "Automatic Live View",
+ "desc": "Automatically switch to a camera's live view when activity is detected. Disabling this option causes static camera images on the Live dashboard to only update once per minute."
+ },
+ "playAlertVideos": {
+ "label": "Play Alert Videos",
+ "desc": "By default, recent alerts on the Live dashboard play as small looping videos. Disable this option to only show a static image of recent alerts on this device/browser."
+ }
+ },
+ "storedLayouts": {
+ "title": "Stored Layouts",
+ "desc": "The layout of cameras in a camera group can be dragged/resized. The positions are stored in your browser's local storage.",
+ "clearAll": "Clear All Layouts"
+ },
+ "cameraGroupStreaming": {
+ "title": "Camera Group Streaming Settings",
+ "desc": "Streaming settings for each camera group are stored in your browser's local storage.",
+ "clearAll": "Clear All Streaming Settings"
+ },
+ "recordingsViewer": {
+ "title": "Recordings Viewer",
+ "defaultPlaybackRate": {
+ "label": "Default Playback Rate",
+ "desc": "Default playback rate for recordings playback."
+ }
+ },
+ "calendar": {
+ "title": "Calendar",
+ "firstWeekday": {
+ "label": "First Weekday",
+ "desc": "The day that the weeks of the review calendar begin on.",
+ "sunday": "Sunday",
+ "monday": "Monday"
+ }
+ },
+ "toast": {
+ "success": {
+ "clearStoredLayout": "Cleared stored layout for {{cameraName}}",
+ "clearStreamingSettings": "Cleared streaming settings for all camera groups."
+ },
+ "error": {
+ "clearStoredLayoutFailed": "Failed to clear stored layout: {{errorMessage}}",
+ "clearStreamingSettingsFailed": "Failed to clear streaming settings: {{errorMessage}}"
+ }
+ }
+ },
+ "classification": {
+ "title": "Classification Settings",
+ "semanticSearch": {
+ "title": "Semantic Search",
+ "desc": "Semantic Search in Frigate allows you to find tracked objects within your review items using either the image itself, a user-defined text description, or an automatically generated one.",
+ "readTheDocumentation": "Read the Documentation",
+ "reindexOnStartup": {
+ "label": "Re-Index On Startup",
+ "desc": "Re-indexing will reprocess all thumbnails and descriptions (if enabled) and apply the embeddings on each startup. Don't forget to disable the option after restarting!"
+ },
+ "modelSize": {
+ "label": "Model Size",
+ "desc": "The size of the model used for semantic search embeddings.",
+ "small": {
+ "title": "small",
+ "desc": "Using small employs a quantized version of the model that uses less RAM and runs faster on CPU with a very negligible difference in embedding quality."
+ },
+ "large": {
+ "title": "large",
+ "desc": "Using large employs the full Jina model and will automatically run on the GPU if applicable."
+ }
+ }
+ },
+ "faceRecognition": {
+ "title": "Face Recognition",
+ "desc": "Face recognition allows people to be assigned names and when their face is recognized Frigate will assign the person's name as a sub label. This information is included in the UI, filters, as well as in notifications.",
+ "readTheDocumentation": "Read the Documentation"
+ },
+ "licensePlateRecognition": {
+ "title": "License Plate Recognition",
+ "desc": "Frigate can recognize license plates on vehicles and automatically add the detected characters to the recognized_license_plate field or a known name as a sub_label to objects that are of type car. A common use case may be to read the license plates of cars pulling into a driveway or cars passing by on a street.",
+ "readTheDocumentation": "Read the Documentation"
+ },
+ "toast": {
+ "success": "Classification settings have been saved.",
+ "error": "Failed to save config changes: {{errorMessage}}"
+ }
+ },
+ "camera": {
+ "title": "Camera Settings",
+ "streams": {
+ "title": "Streams",
+ "desc": "Disabling a camera completely stops Frigate's processing of this camera's streams. Detection, recording, and debugging will be unavailable.Motion Boxes
Red boxes will be overlaid on areas of the frame where motion is currently being detected
" + }, + "regions": { + "title": "Regions", + "desc": "Show a box of the region of interest sent to the object detector", + "tips": "Region Boxes
Bright green boxes will be overlaid on areas of interest in the frame that are being sent to the object detector.
" + }, + "objectShapeFilterDrawing": { + "title": "Object Shape Filter Drawing", + "desc": "Draw a rectangle on the image to view area and ratio details", + "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.", + "document": "Read the documentation ", + "score": "Score", + "ratio": "Ratio", + "area": "Area" + } + }, + "users": { + "title": "Users", + "management": { + "title": "User Management", + "desc": "Manage this Frigate instance's user accounts." + }, + "addUser": "Add User", + "updatePassword": "Update Password", + "toast": { + "success": { + "createUser": "User {{user}} created successfully", + "deleteUser": "User {{user}} deleted successfully", + "updatePassword": "Password updated successfully.", + "roleUpdated": "Role updated for {{user}}" + }, + "error": { + "setPasswordFailed": "Failed to save password: {{errorMessage}}", + "createUserFailed": "Failed to create user: {{errorMessage}}", + "deleteUserFailed": "Failed to delete user: {{errorMessage}}", + "roleUpdateFailed": "Failed to update role: {{errorMessage}}" + } + }, + "table": { + "username": "Username", + "actions": "Actions", + "role": "Role", + "noUsers": "No users found.", + "changeRole": "Change user role", + "password": "Password", + "deleteUser": "Delete user" + }, + "dialog": { + "form": { + "user": { + "title": "Username", + "desc": "Only letters, numbers, periods and underscores allowed.", + "placeholder": "Enter username" + }, + "password": { + "title": "Password", + "placeholder": "Enter password", + "confirm": { + "title": "Confirm Password", + "placeholder": "Confirm Password" + }, + "strength": { + "title": "Password strength: ", + "weak": "Weak", + "medium": "Medium", + "strong": "Strong", + "veryStrong": "Very Strong" + }, + "match": "Passwords match", + "notMatch": "Passwords don't match" + }, + "newPassword": { + "title": "New Password", + "placeholder": "Enter new password", + "confirm": { + "placeholder": "Re-enter new password" + } + }, + "usernameIsRequired": "Username is required" + }, + "createUser": { + "title": "Create New User", + "desc": "Add a new user account and specify an role for access to areas of the Frigate UI.", + "usernameOnlyInclude": "Username may only include letters, numbers, . or _" + }, + "deleteUser": { + "title": "Delete User", + "desc": "This action cannot be undone. This will permanently delete the user account and remove all associated data.", + "warn": "Are you sure you want to delete {{username}}?" + }, + "passwordSetting": { + "updatePassword": "Update Password for {{username}}", + "setPassword": "Set Password", + "desc": "Create a strong password to secure this account." + }, + "changeRole": { + "title": "Change User Role", + "desc": "Update permissions for {{username}}", + "roleInfo": "Select the appropriate role for this user:
https://...). This is a browser limitation. Access Frigate securely to use notifications.",
+ "documentation": "Read the Documentation"
+ },
+ "globalSettings": {
+ "title": "Global Settings",
+ "desc": "Temporarily suspend notifications for specific cameras on all registered devices."
+ },
+ "email": {
+ "title": "Email",
+ "placeholder": "e.g. example@email.com",
+ "desc": "A valid email is required and will be used to notify you if there are any issues with the push service."
+ },
+ "cameras": {
+ "title": "Cameras",
+ "noCameras": "No cameras available",
+ "desc": "Select which cameras to enable notifications for."
+ },
+ "deviceSpecific": "Device Specific Settings",
+ "registerDevice": "Register This Device",
+ "unregisterDevice": "Unregister This Device",
+ "sendTestNotification": "Send a test notification",
+ "active": "Notifications Active",
+ "suspended": "Notifications suspended {{time}}",
+ "suspendTime": {
+ "5minutes": "Suspend for 5 minutes",
+ "10minutes": "Suspend for 10 minutes",
+ "30minutes": "Suspend for 30 minutes",
+ "1hour": "Suspend for 1 hour",
+ "12hours": "Suspend for 12 hours",
+ "24hours": "Suspend for 24 hours",
+ "untilRestart": "Suspend until restart"
+ },
+ "cancelSuspension": "Cancel Suspension",
+ "toast": {
+ "success": {
+ "registered": "Successfully registered for notifications. Restarting Frigate is required before any notifications (including a test notification) can be sent.",
+ "settingSaved": "Notification settings have been saved."
+ },
+ "error": {
+ "registerFailed": "Failed to save notification registration."
+ }
+ }
+ },
+ "frigatePlus": {
+ "title": "Frigate+ Settings",
+ "apiKey": {
+ "title": "Frigate+ API Key",
+ "validated": "Frigate+ API key is detected and validated",
+ "notValidated": "Frigate+ API key is not detected or not validated",
+ "desc": "The Frigate+ API key enables integration with the Frigate+ service.",
+ "plusLink": "Read more about Frigate+"
+ },
+ "snapshotConfig": {
+ "title": "Snapshot Configuration",
+ "desc": "Submitting to Frigate+ requires both snapshots and clean_copy snapshots to be enabled in your config.",
+ "documentation": "Read the documentation",
+ "cleanCopyWarning": "Some cameras have snapshots enabled but have the clean copy disabled. You need to enable clean_copy in your snapshot config to be able to submit images from these cameras to Frigate+.",
+ "table": {
+ "camera": "Camera",
+ "snapshots": "Snapshots",
+ "cleanCopySnapshots": "clean_copy Snapshots"
+ }
+ },
+ "modelInfo": {
+ "title": "Model Information",
+ "modelId": "Model ID",
+ "modelType": "Model Type",
+ "trainDate": "Train Date",
+ "baseModel": "Base Model",
+ "supportedDetectors": "Supported Detectors",
+ "cameras": "Cameras",
+ "loading": "Loading model information...",
+ "error": "Failed to load model information"
+ }
+ }
+}
diff --git a/web/public/locales/en/views/system.json b/web/public/locales/en/views/system.json
new file mode 100644
index 000000000..77516f3e1
--- /dev/null
+++ b/web/public/locales/en/views/system.json
@@ -0,0 +1,156 @@
+{
+ "documentTitle": {
+ "cameras": "Cameras Stats - Frigate",
+ "storage": "Storage Stats - Frigate",
+ "general": "General Stats - Frigate",
+ "features": "Features Stats - Frigate",
+ "logs": {
+ "frigate": "Frigate Logs - Frigate",
+ "go2rtc": "Go2RTC Logs - Frigate",
+ "nginx": "Nginx Logs - Frigate"
+ }
+ },
+ "title": "System",
+ "metrics": "System metrics",
+ "logs": {
+ "download": {
+ "label": "Download Logs"
+ },
+ "copy": {
+ "label": "Copy to Clipboard",
+ "success": "Copied logs to clipboard",
+ "error": "Could not copy logs to clipboard"
+ },
+ "type": {
+ "label": "Type",
+ "timestamp": "Timestamp",
+ "tag": "Tag",
+ "message": "Message"
+ },
+ "tips": "Logs are streaming from the server",
+ "toast": {
+ "error": {
+ "fetchingLogsFailed": "Error fetching logs: {{errorMessage}}",
+ "whileStreamingLogs": "Error while streaming logs: {{errorMessage}}"
+ }
+ }
+ },
+ "general": {
+ "title": "General",
+ "detector": {
+ "title": "Detectors",
+ "inferenceSpeed": "Detector Inference Speed",
+ "cpuUsage": "Detector CPU Usage",
+ "memoryUsage": "Detector Memory Usage"
+ },
+ "hardwareInfo": {
+ "title": "Hardware Info",
+ "gpuUsage": "GPU Usage",
+ "gpuMemory": "GPU Memory",
+ "gpuEncoder": "GPU Encoder",
+ "gpuDecoder": "GPU Decoder",
+ "gpuInfo": {
+ "vainfoOutput": {
+ "title": "Vainfo Output",
+ "returnCode": "Return Code: {{code}}",
+ "processOutput": "Process Output:",
+ "processError": "Process Error:"
+ },
+ "nvidiaSMIOutput": {
+ "title": "Nvidia SMI Output",
+ "name": "Name: {{name}}",
+ "driver": "Driver: {{driver}}",
+ "cudaComputerCapability": "CUDA Compute Capability: {{cuda_compute}}",
+ "vbios": "VBios Info: {{vbios}}"
+ },
+ "closeInfo": {
+ "label": "Close GPU info"
+ },
+ "copyInfo": {
+ "label": "Copy GPU info"
+ },
+ "toast": {
+ "success": "Copied GPU info to clipboard"
+ }
+ }
+ },
+ "otherProcesses": {
+ "title": "Other Processes",
+ "processCpuUsage": "Process CPU Usage",
+ "processMemoryUsage": "Process Memory Usage"
+ }
+ },
+ "storage": {
+ "title": "Storage",
+ "overview": "Overview",
+ "recordings": {
+ "title": "Recordings",
+ "tips": "This value represents the total storage used by the recordings in Frigate's database. Frigate does not track storage usage for all files on your disk.",
+ "earliestRecording": "Earliest recording available:"
+ },
+ "cameraStorage": {
+ "title": "Camera Storage",
+ "camera": "Camera",
+ "unusedStorageInformation": "Unused Storage Information",
+ "storageUsed": "Storage",
+ "percentageOfTotalUsed": "Percentage of Total",
+ "bandwidth": "Bandwidth",
+ "unused": {
+ "title": "Unused",
+ "tips": "This value may not accurately represent the free space available to Frigate if you have other files stored on your drive beyond Frigate's recordings. Frigate does not track storage usage outside of its recordings."
+ }
+ }
+ },
+ "cameras": {
+ "title": "Cameras",
+ "overview": "Overview",
+ "info": {
+ "cameraProbeInfo": "{{camera}} Camera Probe Info",
+ "streamDataFromFFPROBE": "Stream data is obtained with ffprobe.",
+ "fetching": "Fetching Camera Data",
+ "stream": "Stream {{idx}}",
+ "video": "Video:",
+ "codec": "Codec:",
+ "resolution": "Resolution:",
+ "fps": "FPS:",
+ "unknown": "Unknown",
+ "audio": "Audio:",
+ "error": "Error: {{error}}",
+ "tips": {
+ "title": "Camera Probe Info"
+ }
+ },
+ "framesAndDetections": "Frames / Detections",
+ "label": {
+ "camera": "camera",
+ "detect": "detect",
+ "skipped": "skipped",
+ "ffmpeg": "ffmpeg",
+ "capture": "capture"
+ },
+ "toast": {
+ "success": {
+ "copyToClipboard": "Copied probe data to clipboard."
+ },
+ "error": {
+ "unableToProbeCamera": "Unable to probe camera: {{errorMessage}}"
+ }
+ }
+ },
+ "lastRefreshed": "Last refreshed: ",
+ "stats": {
+ "ffmpegHighCpuUsage": "{{camera}} has high FFMPEG CPU usage ({{ffmpegAvg}}%)",
+ "detectHighCpuUsage": "{{camera}} has high detect CPU usage ({{detectAvg}}%)",
+ "healthy": "System is healthy",
+ "reindexingEmbeddings": "Reindexing embeddings ({{processed}}% complete)"
+ },
+ "features": {
+ "title": "Features",
+ "embeddings": {
+ "image_embedding_speed": "Image Embedding Speed",
+ "face_embedding_speed": "Face Embedding Speed",
+ "plate_recognition_speed": "Plate Recognition Speed",
+ "text_embedding_speed": "Text Embedding Speed"
+ }
+ }
+}
diff --git a/web/public/locales/zh-CN/audio.json b/web/public/locales/zh-CN/audio.json
new file mode 100644
index 000000000..2c65847e3
--- /dev/null
+++ b/web/public/locales/zh-CN/audio.json
@@ -0,0 +1,429 @@
+{
+ "speech": "谈话",
+ "babbling": "喋喋不休",
+ "yell": "大喊",
+ "bellow": "吼叫",
+ "whoop": "欢呼",
+ "whispering": "耳语",
+ "laughter": "笑声",
+ "snicker": "窃笑",
+ "crying": "哭泣",
+ "sigh": "叹息",
+ "singing": "唱歌",
+ "choir": "合唱",
+ "yodeling": "山歌",
+ "chant": "吟唱",
+ "mantra": "咒语",
+ "child_singing": "儿童歌唱",
+ "synthetic_singing": "合成歌声",
+ "rapping": "说唱",
+ "humming": "哼唱",
+ "groan": "呻吟",
+ "grunt": "咕哝",
+ "whistling": "口哨",
+ "breathing": "呼吸",
+ "wheeze": "喘息",
+ "snoring": "打鼾",
+ "gasp": "倒抽气",
+ "pant": "喘气",
+ "snort": "哼声",
+ "cough": "咳嗽",
+ "throat_clearing": "清嗓子",
+ "sneeze": "打喷嚏",
+ "sniff": "抽鼻子",
+ "run": "跑步",
+ "shuffle": "拖步",
+ "footsteps": "脚步声",
+ "chewing": "咀嚼",
+ "biting": "咬",
+ "gargling": "漱口",
+ "stomach_rumble": "肚子咕噜",
+ "burping": "打嗝",
+ "hiccup": "打嗝",
+ "fart": "放屁",
+ "hands": "手",
+ "finger_snapping": "打响指",
+ "clapping": "鼓掌",
+ "heartbeat": "心跳",
+ "heart_murmur": "心脏杂音",
+ "cheering": "欢呼",
+ "applause": "掌声",
+ "chatter": "闲聊",
+ "crowd": "人群",
+ "children_playing": "儿童玩耍",
+ "animal": "动物",
+ "pets": "宠物",
+ "dog": "狗",
+ "bark": "吠叫",
+ "yip": "吠叫",
+ "howl": "嚎叫",
+ "bow_wow": "汪汪",
+ "growling": "咆哮",
+ "whimper_dog": "狗呜咽",
+ "cat": "猫",
+ "purr": "咕噜",
+ "meow": "喵喵",
+ "hiss": "嘶嘶声",
+ "caterwaul": "猫叫春",
+ "livestock": "牲畜",
+ "horse": "马",
+ "clip_clop": "蹄声",
+ "neigh": "嘶鸣",
+ "cattle": "牛",
+ "moo": "哞哞",
+ "cowbell": "牛铃",
+ "pig": "猪",
+ "oink": "哼哼",
+ "goat": "山羊",
+ "bleat": "咩咩",
+ "sheep": "绵羊",
+ "fowl": "家禽",
+ "chicken": "鸡",
+ "cluck": "咯咯",
+ "cock_a_doodle_doo": "喔喔",
+ "turkey": "火鸡",
+ "gobble": "咯咯",
+ "duck": "鸭子",
+ "quack": "嘎嘎",
+ "goose": "鹅",
+ "honk": "鸣笛/鹅叫声",
+ "wild_animals": "野生动物",
+ "roaring_cats": "吼叫的猫科动物",
+ "roar": "吼叫",
+ "bird": "鸟",
+ "chirp": "啾啾",
+ "squawk": "啼叫",
+ "pigeon": "鸽子",
+ "coo": "咕咕",
+ "crow": "乌鸦",
+ "caw": "呱呱",
+ "owl": "猫头鹰",
+ "hoot": "呜呜",
+ "flapping_wings": "翅膀拍打",
+ "dogs": "狗群",
+ "rats": "老鼠",
+ "mouse": "老鼠",
+ "patter": "啪嗒声",
+ "insect": "昆虫",
+ "cricket": "蟋蟀",
+ "mosquito": "蚊子",
+ "fly": "苍蝇",
+ "buzz": "嗡嗡",
+ "frog": "青蛙",
+ "croak": "呱呱",
+ "snake": "蛇",
+ "rattle": "响尾",
+ "whale_vocalization": "鲸鱼叫声",
+ "music": "音乐",
+ "musical_instrument": "乐器",
+ "plucked_string_instrument": "弹拨乐器",
+ "guitar": "吉他",
+ "electric_guitar": "电吉他",
+ "bass_guitar": "贝斯",
+ "acoustic_guitar": "原声吉他",
+ "steel_guitar": "钢弦吉他",
+ "tapping": "敲击",
+ "strum": "扫弦",
+ "banjo": "班卓琴",
+ "sitar": "西塔琴",
+ "mandolin": "曼陀林",
+ "zither": "古筝",
+ "ukulele": "尤克里里",
+ "keyboard": "键盘",
+ "piano": "钢琴",
+ "electric_piano": "电钢琴",
+ "organ": "风琴",
+ "electronic_organ": "电子琴",
+ "hammond_organ": "哈蒙德风琴",
+ "synthesizer": "合成器",
+ "sampler": "采样器",
+ "harpsichord": "大键琴",
+ "percussion": "打击乐器",
+ "drum_kit": "架子鼓",
+ "drum_machine": "鼓机",
+ "drum": "鼓",
+ "snare_drum": "军鼓",
+ "rimshot": "鼓边击",
+ "drum_roll": "滚鼓",
+ "bass_drum": "大鼓",
+ "timpani": "定音鼓",
+ "tabla": "塔布拉鼓",
+ "cymbal": "钹",
+ "hi_hat": "踩镲",
+ "wood_block": "木鱼",
+ "tambourine": "铃鼓",
+ "maraca": "沙锤",
+ "gong": "锣",
+ "tubular_bells": "管钟",
+ "mallet_percussion": "槌击打击乐器",
+ "marimba": "马林巴",
+ "glockenspiel": "钟琴",
+ "vibraphone": "颤音琴",
+ "steelpan": "钢鼓",
+ "orchestra": "管弦乐队",
+ "brass_instrument": "铜管乐器",
+ "french_horn": "圆号",
+ "trumpet": "小号",
+ "trombone": "长号",
+ "bowed_string_instrument": "弓弦乐器",
+ "string_section": "弦乐组",
+ "violin": "小提琴",
+ "pizzicato": "拨弦",
+ "cello": "大提琴",
+ "double_bass": "低音提琴",
+ "wind_instrument": "管乐器",
+ "flute": "长笛",
+ "saxophone": "萨克斯",
+ "clarinet": "单簧管",
+ "harp": "竖琴",
+ "bell": "铃",
+ "church_bell": "教堂钟",
+ "jingle_bell": "铃铛",
+ "bicycle_bell": "自行车铃",
+ "tuning_fork": "音叉",
+ "chime": "风铃",
+ "wind_chime": "风铃",
+ "harmonica": "口琴",
+ "accordion": "手风琴",
+ "bagpipes": "风笛",
+ "didgeridoo": "迪吉里杜管",
+ "theremin": "特雷门琴",
+ "singing_bowl": "颂钵",
+ "scratching": "刮擦声",
+ "pop_music": "流行音乐",
+ "hip_hop_music": "嘻哈音乐",
+ "beatboxing": "人声节拍",
+ "rock_music": "摇滚音乐",
+ "heavy_metal": "重金属",
+ "punk_rock": "朋克摇滚",
+ "grunge": "垃圾摇滚",
+ "progressive_rock": "前卫摇滚",
+ "rock_and_roll": "摇滚乐",
+ "psychedelic_rock": "迷幻摇滚",
+ "rhythm_and_blues": "节奏布鲁斯",
+ "soul_music": "灵魂乐",
+ "reggae": "雷鬼",
+ "country": "乡村音乐",
+ "swing_music": "摇摆乐",
+ "bluegrass": "蓝草音乐",
+ "funk": "放克",
+ "folk_music": "民谣",
+ "middle_eastern_music": "中东音乐",
+ "jazz": "爵士乐",
+ "disco": "迪斯科",
+ "classical_music": "古典音乐",
+ "opera": "歌剧",
+ "electronic_music": "电子音乐",
+ "house_music": "浩室音乐",
+ "techno": "科技舞曲",
+ "dubstep": "回响贝斯",
+ "drum_and_bass": "鼓打贝斯",
+ "electronica": "电子乐",
+ "electronic_dance_music": "电子舞曲",
+ "ambient_music": "环境音乐",
+ "trance_music": "迷幻舞曲",
+ "music_of_latin_america": "拉丁美洲音乐",
+ "salsa_music": "萨尔萨",
+ "flamenco": "弗拉门戈",
+ "blues": "蓝调",
+ "music_for_children": "儿童音乐",
+ "new-age_music": "新世纪音乐",
+ "vocal_music": "声乐",
+ "a_capella": "无伴奏合唱",
+ "music_of_africa": "非洲音乐",
+ "afrobeat": "非洲节拍",
+ "christian_music": "基督教音乐",
+ "gospel_music": "福音音乐",
+ "music_of_asia": "亚洲音乐",
+ "carnatic_music": "卡纳提克音乐",
+ "music_of_bollywood": "宝莱坞音乐",
+ "ska": "斯卡",
+ "traditional_music": "传统音乐",
+ "independent_music": "独立音乐",
+ "song": "歌曲",
+ "background_music": "背景音乐",
+ "theme_music": "主题音乐",
+ "jingle": "广告歌",
+ "soundtrack_music": "配乐",
+ "lullaby": "摇篮曲",
+ "video_game_music": "电子游戏音乐",
+ "christmas_music": "圣诞音乐",
+ "dance_music": "舞曲",
+ "wedding_music": "婚礼音乐",
+ "happy_music": "欢快音乐",
+ "sad_music": "悲伤音乐",
+ "tender_music": "温柔音乐",
+ "exciting_music": "激动音乐",
+ "angry_music": "愤怒音乐",
+ "scary_music": "恐怖音乐",
+ "wind": "风",
+ "rustling_leaves": "树叶沙沙声",
+ "wind_noise": "风声",
+ "thunderstorm": "雷暴",
+ "thunder": "雷声",
+ "water": "水",
+ "rain": "雨",
+ "raindrop": "雨滴",
+ "rain_on_surface": "雨打表面",
+ "stream": "溪流",
+ "waterfall": "瀑布",
+ "ocean": "海洋",
+ "waves": "波浪",
+ "steam": "蒸汽",
+ "gurgling": "汩汩声",
+ "fire": "火",
+ "crackle": "噼啪声",
+ "vehicle": "车辆",
+ "boat": "船",
+ "sailboat": "帆船",
+ "rowboat": "划艇",
+ "motorboat": "摩托艇",
+ "ship": "轮船",
+ "motor_vehicle": "机动车",
+ "car": "汽车",
+ "toot": "鸣笛",
+ "car_alarm": "汽车警报",
+ "power_windows": "电动车窗",
+ "skidding": "轮胎打滑",
+ "tire_squeal": "轮胎尖叫",
+ "car_passing_by": "汽车驶过",
+ "race_car": "赛车",
+ "truck": "卡车",
+ "air_brake": "气闸",
+ "air_horn": "气笛",
+ "reversing_beeps": "倒车提示音",
+ "ice_cream_truck": "冰淇淋车",
+ "bus": "公共汽车",
+ "emergency_vehicle": "应急车辆",
+ "police_car": "警车",
+ "ambulance": "救护车",
+ "fire_engine": "消防车",
+ "motorcycle": "摩托车",
+ "traffic_noise": "交通噪音",
+ "rail_transport": "铁路运输",
+ "train": "火车",
+ "train_whistle": "火车汽笛",
+ "train_horn": "火车鸣笛",
+ "railroad_car": "铁路车厢",
+ "train_wheels_squealing": "火车轮子尖叫",
+ "subway": "地铁",
+ "aircraft": "飞行器",
+ "aircraft_engine": "飞机引擎",
+ "jet_engine": "喷气引擎",
+ "propeller": "螺旋桨",
+ "helicopter": "直升机",
+ "fixed-wing_aircraft": "固定翼飞机",
+ "bicycle": "自行车",
+ "skateboard": "滑板",
+ "engine": "引擎",
+ "light_engine": "轻型引擎",
+ "dental_drill's_drill": "牙科钻",
+ "lawn_mower": "割草机",
+ "chainsaw": "电锯",
+ "medium_engine": "中型引擎",
+ "heavy_engine": "重型引擎",
+ "engine_knocking": "引擎敲击",
+ "engine_starting": "引擎启动",
+ "idling": "怠速",
+ "accelerating": "加速",
+ "door": "门",
+ "doorbell": "门铃",
+ "ding-dong": "叮咚",
+ "sliding_door": "滑动门",
+ "slam": "猛关",
+ "knock": "敲门",
+ "tap": "轻敲",
+ "squeak": "吱吱声",
+ "cupboard_open_or_close": "橱柜开关",
+ "drawer_open_or_close": "抽屉开关",
+ "dishes": "餐具",
+ "cutlery": "刀叉",
+ "chopping": "切菜",
+ "frying": "煎炸",
+ "microwave_oven": "微波炉",
+ "blender": "搅拌机",
+ "water_tap": "水龙头",
+ "sink": "水槽",
+ "bathtub": "浴缸",
+ "hair_dryer": "吹风机",
+ "toilet_flush": "马桶冲水",
+ "toothbrush": "牙刷",
+ "electric_toothbrush": "电动牙刷",
+ "vacuum_cleaner": "吸尘器",
+ "zipper": "拉链",
+ "keys_jangling": "钥匙叮当",
+ "coin": "硬币",
+ "scissors": "剪刀",
+ "electric_shaver": "电动剃须刀",
+ "shuffling_cards": "洗牌",
+ "typing": "打字",
+ "typewriter": "打字机",
+ "computer_keyboard": "电脑键盘",
+ "writing": "书写",
+ "alarm": "警报",
+ "telephone": "电话",
+ "telephone_bell_ringing": "电话铃声",
+ "ringtone": "手机铃声",
+ "telephone_dialing": "电话拨号",
+ "dial_tone": "拨号音",
+ "busy_signal": "忙音",
+ "alarm_clock": "闹钟",
+ "siren": "警笛",
+ "civil_defense_siren": "防空警报",
+ "buzzer": "蜂鸣器",
+ "smoke_detector": "烟雾探测器",
+ "fire_alarm": "火灾警报器",
+ "foghorn": "雾笛",
+ "whistle": "哨子",
+ "steam_whistle": "蒸汽汽笛",
+ "mechanisms": "机械装置",
+ "ratchet": "棘轮",
+ "clock": "时钟",
+ "tick": "滴答",
+ "tick-tock": "滴答滴答",
+ "gears": "齿轮",
+ "pulleys": "滑轮",
+ "sewing_machine": "缝纫机",
+ "mechanical_fan": "机械风扇",
+ "air_conditioning": "空调",
+ "cash_register": "收银机",
+ "printer": "打印机",
+ "camera": "相机",
+ "single-lens_reflex_camera": "单反相机",
+ "tools": "工具",
+ "hammer": "锤子",
+ "jackhammer": "风镐",
+ "sawing": "锯",
+ "filing": "锉",
+ "sanding": "砂磨",
+ "power_tool": "电动工具",
+ "drill": "电钻",
+ "explosion": "爆炸",
+ "gunshot": "枪声",
+ "machine_gun": "机关枪",
+ "fusillade": "齐射",
+ "artillery_fire": "炮火",
+ "cap_gun": "玩具枪",
+ "fireworks": "烟花",
+ "firecracker": "鞭炮",
+ "burst": "爆裂",
+ "eruption": "爆发",
+ "boom": "轰隆",
+ "wood": "木头",
+ "chop": "砍",
+ "splinter": "碎裂",
+ "crack": "破裂",
+ "glass": "玻璃",
+ "chink": "叮当",
+ "shatter": "粉碎",
+ "silence": "寂静",
+ "sound_effect": "音效",
+ "environmental_noise": "环境噪音",
+ "static": "静电噪音",
+ "white_noise": "白噪音",
+ "pink_noise": "粉红噪音",
+ "television": "电视",
+ "radio": "收音机",
+ "field_recording": "实地录音",
+ "scream": "尖叫"
+}
diff --git a/web/public/locales/zh-CN/common.json b/web/public/locales/zh-CN/common.json
new file mode 100644
index 000000000..aa2d9a825
--- /dev/null
+++ b/web/public/locales/zh-CN/common.json
@@ -0,0 +1,201 @@
+{
+ "time": {
+ "untilForTime": "直到 {{time}}",
+ "untilForRestart": "直到 Frigate 重启。",
+ "untilRestart": "直到重启",
+ "ago": "{{timeAgo}} 前",
+ "justNow": "刚才",
+ "today": "今天",
+ "yesterday": "昨天",
+ "last7": "最后 7 天",
+ "last14": "最后 14 天",
+ "last30": "最后 30 天",
+ "thisWeek": "本周",
+ "lastWeek": "上个周",
+ "thisMonth": "本月",
+ "lastMonth": "上个月",
+ "5minutes": "5 分钟",
+ "10minutes": "10 分钟",
+ "30minutes": "30 分钟",
+ "1hour": "1 小时",
+ "12hours": "12 小时",
+ "24hours": "24 小时",
+ "pm": "下午",
+ "am": "上午",
+ "yr": "{{time}}年",
+ "year": "{{time}}年",
+ "mo": "{{time}}月",
+ "month": "{{time}}月",
+ "d": "{{time}}天",
+ "day": "{{time}}天",
+ "h": "{{time}}小时",
+ "hour": "{{time}}小时",
+ "m": "{{time}}分钟",
+ "minute": "{{time}}分钟",
+ "s": "{{time}}秒",
+ "second": "{{time}}秒",
+ "formattedTimestamp": {
+ "12hour": "%m月%-d日 %I:%M:%S %p",
+ "24hour": "%m月%-d日 %H:%M:%S"
+ },
+ "formattedTimestamp2": {
+ "12hour": "%m/%d %I:%M:%S%P",
+ "24hour": "%d日%m月 %H:%M:%S"
+ },
+ "formattedTimestampExcludeSeconds": {
+ "12hour": "%m月%-d日 %I:%M %p",
+ "24hour": "%m月%-d日 %H:%M"
+ },
+ "formattedTimestampWithYear": {
+ "12hour": "%Y年%m月%-d日 %I:%M:%S %p",
+ "24hour": "%Y年%m月%-d日 %H:%M"
+ },
+ "formattedTimestampOnlyMonthAndDay": "%m月%-d日"
+ },
+ "unit": {
+ "speed": {
+ "mph": "英里/小时",
+ "kph": "公里/小时"
+ }
+ },
+ "label": {
+ "back": "返回"
+ },
+ "pagination": {
+ "label": "分页",
+ "previous": {
+ "title": "上一页",
+ "label": "转到上一页"
+ },
+ "next": {
+ "title": "下一页",
+ "label": "转到下一页"
+ },
+ "more": "更多页面"
+ },
+ "button": {
+ "apply": "应用",
+ "reset": "重置",
+ "done": "完成",
+ "enabled": "启用",
+ "enable": "启用",
+ "disabled": "禁用",
+ "disable": "禁用",
+ "save": "保存",
+ "saving": "保存中……",
+ "cancel": "取消",
+ "close": "关闭",
+ "copy": "复制",
+ "back": "返回",
+ "history": "历史",
+ "fullscreen": "全屏",
+ "exitFullscreen": "退出全屏",
+ "pictureInPicture": "画中画",
+ "on": "开",
+ "off": "关",
+ "edit": "编辑",
+ "copyCoordinates": "复制坐标",
+ "delete": "删除",
+ "yes": "是",
+ "no": "否",
+ "download": "下载",
+ "info": "信息",
+ "suspended": "已暂停",
+ "unsuspended": "取消暂停",
+ "play": "播放",
+ "unselect": "取消选择",
+ "export": "导出",
+ "deleteNow": "立即删除",
+ "next": "下一个"
+ },
+ "menu": {
+ "system": "系统",
+ "systemMetrics": "系统信息",
+ "configuration": "配置",
+ "systemLogs": "系统日志",
+ "settings": "设置",
+ "configurationEditor": "配置编辑器",
+ "languages": "Languages / 语言",
+ "language": {
+ "en": "English",
+ "zhCN": "简体中文",
+ "withSystem": {
+ "label": "使用系统语言设置"
+ }
+ },
+ "appearance": "外观",
+ "darkMode": {
+ "label": "深色模式",
+ "light": "浅色",
+ "dark": "深色",
+ "withSystem": {
+ "label": "使用系统深色模式设置"
+ }
+ },
+ "withSystem": "跟随系统",
+ "theme": {
+ "label": "主题",
+ "blue": "蓝色",
+ "green": "绿色",
+ "nord": "Nord",
+ "red": "红色",
+ "contrast": "高对比度",
+ "default": "默认"
+ },
+ "help": "帮助",
+ "documentation": {
+ "title": "文档",
+ "label": "Frigate 的官方文档"
+ },
+ "live": {
+ "title": "实时监控",
+ "allCameras": "所有摄像头",
+ "cameras": {
+ "title": "摄像头",
+ "count_one": "{{count}} 个摄像头",
+ "count_other": "{{count}} 个摄像头"
+ }
+ },
+ "review": "回放",
+ "explore": "探测",
+ "export": "导出",
+ "uiPlayground": "UI 演示",
+ "faceLibrary": "人脸管理",
+ "user": {
+ "account": "账号",
+ "current": "当前用户:{{user}}",
+ "anonymous": "匿名",
+ "logout": "登出",
+ "setPassword": "设置密码",
+ "title": "用户"
+ },
+ "restart": "重启 Frigate"
+ },
+ "toast": {
+ "copyUrlToClipboard": "已复制链接到剪贴板。",
+ "save": {
+ "title": "保存",
+ "error": {
+ "title": "保存配置信息失败: {{errorMessage}}",
+ "noMessage": "保存配置信息失败"
+ }
+ }
+ },
+ "role": {
+ "title": "权限组",
+ "admin": "管理员",
+ "viewer": "查看者",
+ "desc": "管理员可以完全访问 Frigate UI 的所有功能。查看者则仅限于在 UI 中查看摄像头、审核项和历史录像。"
+ },
+ "accessDenied": {
+ "documentTitle": "没有权限 - Frigate",
+ "title": "没有权限",
+ "desc": "您没有权限查看此页面。"
+ },
+ "notFound": {
+ "documentTitle": "没有找到页面 - Frigate",
+ "title": "404",
+ "desc": "页面未找到"
+ },
+ "selectItem": "选择 {{item}}"
+}
diff --git a/web/public/locales/zh-CN/components/auth.json b/web/public/locales/zh-CN/components/auth.json
new file mode 100644
index 000000000..015fa0ba8
--- /dev/null
+++ b/web/public/locales/zh-CN/components/auth.json
@@ -0,0 +1,15 @@
+{
+ "form": {
+ "user": "用户名",
+ "password": "密码",
+ "login": "登录",
+ "errors": {
+ "usernameRequired": "用户名不能为空",
+ "passwordRequired": "密码不能为空",
+ "rateLimit": "超出请求限制,请稍后再试。",
+ "loginFailed": "登录失败",
+ "unknownError": "未知错误,请检查日志。",
+ "webUnknownError": "未知错误,请检查控制台日志。"
+ }
+ }
+}
diff --git a/web/public/locales/zh-CN/components/camera.json b/web/public/locales/zh-CN/components/camera.json
new file mode 100644
index 000000000..347258580
--- /dev/null
+++ b/web/public/locales/zh-CN/components/camera.json
@@ -0,0 +1,83 @@
+{
+ "group": {
+ "label": "摄像头组",
+ "add": "添加摄像头组",
+ "edit": "编辑摄像头组",
+ "delete": {
+ "label": "删除摄像头组",
+ "confirm": {
+ "title": "确认删除",
+ "desc": "你确定要删除摄像头组 {{name}} 吗?"
+ }
+ },
+ "name": {
+ "label": "名称",
+ "placeholder": "请输入名称",
+ "errorMessage": {
+ "mustLeastCharacters": "摄像头组的名称必须至少有 2 个字符。",
+ "exists": "摄像头组名称已存在。",
+ "nameMustNotPeriod": "摄像头组名称不能包含英文句号(.)。",
+ "invalid": "无效的摄像头组名称。"
+ }
+ },
+ "cameras": {
+ "label": "摄像头",
+ "desc": "选择添加至该组的摄像头。"
+ },
+ "icon": "图标",
+ "success": "摄像头组({{name}})保存成功。",
+ "camera": {
+ "setting": {
+ "label": "摄像头视频流设置",
+ "title": "{{cameraName}} 视频流设置",
+ "desc": "更改此摄像头组仪表板的实时视频流选项。这些设置特定于设备/浏览器。",
+ "audioIsAvailable": "此视频流支持音频",
+ "audioIsUnavailable": "此视频流不支持音频",
+ "audio": {
+ "tips": {
+ "title": "音频必须从您的摄像头输出并在 go2rtc 中配置此流。",
+ "document": "阅读文档(英文) "
+ }
+ },
+ "streamMethod": {
+ "label": "视频流方法",
+ "method": {
+ "noStreaming": {
+ "label": "无视频流",
+ "desc": "摄像头图像每分钟仅更新一次,不会进行实时视频流播放。"
+ },
+ "smartStreaming": {
+ "label": "智能视频流(推荐)",
+ "desc": "智能视频流在没有检测到活动时,每分钟更新一次摄像头图像,以节省带宽和资源。当检测到活动时,图像会无缝切换到实时视频流。"
+ },
+ "continuousStreaming": {
+ "label": "持续视频流",
+ "desc": {
+ "title": "当摄像头画面在仪表板上可见时,始终为实时视频流,即使未检测到活动。",
+ "warning": "持续视频流可能会导致高带宽使用和性能问题,请谨慎使用。"
+ }
+ }
+ }
+ },
+ "compatibilityMode": {
+ "label": "兼容模式",
+ "desc": "仅在摄像头的实时视频流显示颜色伪影,并且图像右侧有一条对角线时启用此选项。"
+ }
+ }
+ }
+ },
+ "debug": {
+ "options": {
+ "label": "设置",
+ "title": "选项",
+ "showOptions": "显示选项",
+ "hideOptions": "隐藏选项"
+ },
+ "boundingBox": "边界框",
+ "timestamp": "时间戳",
+ "zones": "区域",
+ "mask": "遮罩",
+ "motion": "运动",
+ "regions": "区域"
+ }
+}
diff --git a/web/public/locales/zh-CN/components/dialog.json b/web/public/locales/zh-CN/components/dialog.json
new file mode 100644
index 000000000..92c574f12
--- /dev/null
+++ b/web/public/locales/zh-CN/components/dialog.json
@@ -0,0 +1,113 @@
+{
+ "restart": {
+ "title": "你确定要重启 Frigate?",
+ "button": "重启",
+ "restarting": {
+ "title": "Frigate 正在重启",
+ "content": "该页面将会在 {{countdown}} 秒后自动刷新。",
+ "button": "强制刷新"
+ }
+ },
+ "explore": {
+ "plus": {
+ "submitToPlus": {
+ "label": "提交至 Frigate+",
+ "desc": "您希望避开的地点中的物体不应被视为误报。若将其作为误报提交,可能会导致AI模型容易混淆相关物体的识别。"
+ },
+ "review": {
+ "true": {
+ "label": "为 Frigate Plus 确认此标签",
+ "true_one": "这是 {{label}}",
+ "true_other": "这是 {{label}}"
+ },
+ "false": {
+ "label": "不为 Frigate Plus 确认此标签",
+ "false_one": "这不是 {{label}}",
+ "false_other": "这不是 {{label}}"
+ },
+ "state": {
+ "submitted": "已提交"
+ }
+ }
+ },
+ "video": {
+ "viewInHistory": "在历史中查看"
+ }
+ },
+ "export": {
+ "time": {
+ "fromTimeline": "从时间线选择",
+ "lastHour_one": "最后1小时",
+ "lastHour_other": "最后 {{count}} 小时",
+ "custom": "自定义",
+ "start": {
+ "title": "开始时间",
+ "label": "选择开始时间"
+ },
+ "end": {
+ "title": "结束时间",
+ "label": "选择结束时间"
+ }
+ },
+ "name": {
+ "placeholder": "导出项目的名字"
+ },
+ "select": "选择",
+ "export": "导出",
+ "selectOrExport": "选择或导出",
+ "toast": {
+ "success": "导出成功。进入 /exports 目录查看文件。",
+ "error": {
+ "failed": "导出失败:{{error}}",
+ "endTimeMustAfterStartTime": "结束时间必须在开始时间之后",
+ "noVaildTimeSelected": "未选择有效的时间范围"
+ }
+ },
+ "fromTimeline": {
+ "saveExport": "保存导出",
+ "previewExport": "预览导出"
+ }
+ },
+ "streaming": {
+ "label": "视频流",
+ "restreaming": {
+ "disabled": "此摄像头未启用视频流转发功能。",
+ "desc": {
+ "title": "为此摄像头设置 go2rtc,以获取额外的实时预览选项和音频支持。",
+ "readTheDocumentation": "阅读文档(英文) "
+ }
+ },
+ "showStats": {
+ "label": "显示视频流统计信息",
+ "desc": "启用后将在摄像头画面上叠加显示视频流统计信息。"
+ },
+ "debugView": "调试界面"
+ },
+ "search": {
+ "saveSearch": {
+ "label": "保存搜索",
+ "desc": "请为此已保存的搜索提供一个名称。",
+ "placeholder": "请输入搜索名称",
+ "overwrite": "{{searchName}} 已存在。保存将覆盖现有值。",
+ "success": "搜索 ({{searchName}}) 已保存。",
+ "button": {
+ "save": {
+ "label": "保存此搜索"
+ }
+ }
+ }
+ },
+ "recording": {
+ "confirmDelete": {
+ "title": "确认删除",
+ "desc": {
+ "selected": "您确定要删除与此审核项相关的所有录制视频吗?detect 流上接收到任何帧,请检查错误日志"
+ },
+ "cameraDisabled": "摄像机已禁用",
+ "stats": {
+ "streamType": {
+ "title": "流类型:",
+ "short": "类型"
+ },
+ "bandwidth": {
+ "title": "带宽:",
+ "short": "带宽"
+ },
+ "latency": {
+ "title": "延迟:",
+ "value": "{{seconds}} 秒",
+ "short": {
+ "title": "延迟",
+ "value": "{{seconds}} 秒"
+ }
+ },
+ "totalFrames": "总帧数:",
+ "droppedFrames": {
+ "title": "丢帧数:",
+ "short": {
+ "title": "丢帧",
+ "value": "{{droppedFrames}} 帧"
+ }
+ },
+ "decodedFrames": "解码帧数:",
+ "droppedFrameRate": "丢帧率:"
+ },
+ "toast": {
+ "success": {
+ "submittedFrigatePlus": "已成功提交帧到 Frigate+"
+ },
+ "error": {
+ "submitFrigatePlusFailed": "提交帧到 Frigate+ 失败"
+ }
+ }
+}
diff --git a/web/public/locales/zh-CN/objects.json b/web/public/locales/zh-CN/objects.json
new file mode 100644
index 000000000..80a7893ae
--- /dev/null
+++ b/web/public/locales/zh-CN/objects.json
@@ -0,0 +1,120 @@
+{
+ "person": "人",
+ "bicycle": "自行车",
+ "car": "汽车",
+ "motorcycle": "摩托车",
+ "airplane": "飞机",
+ "bus": "公交车",
+ "train": "火车",
+ "boat": "船",
+ "traffic_light": "交通灯",
+ "fire_hydrant": "消防栓",
+ "street_sign": "路标",
+ "stop_sign": "停车标志",
+ "parking_meter": "停车计时器",
+ "bench": "长椅",
+ "bird": "鸟",
+ "cat": "猫",
+ "dog": "狗",
+ "horse": "马",
+ "sheep": "羊",
+ "cow": "牛",
+ "elephant": "大象",
+ "bear": "熊",
+ "zebra": "斑马",
+ "giraffe": "长颈鹿",
+ "hat": "帽子",
+ "backpack": "背包",
+ "umbrella": "雨伞",
+ "shoe": "鞋子",
+ "eye_glasses": "眼镜",
+ "handbag": "手提包",
+ "tie": "领带",
+ "suitcase": "手提箱",
+ "frisbee": "飞盘",
+ "skis": "滑雪板",
+ "snowboard": "滑雪板",
+ "sports_ball": "运动球",
+ "kite": "风筝",
+ "baseball_bat": "棒球棒",
+ "baseball_glove": "棒球手套",
+ "skateboard": "滑板",
+ "surfboard": "冲浪板",
+ "tennis_racket": "网球拍",
+ "bottle": "瓶子",
+ "plate": "盘子",
+ "wine_glass": "酒杯",
+ "cup": "杯子",
+ "fork": "叉子",
+ "knife": "刀",
+ "spoon": "勺子",
+ "bowl": "碗",
+ "banana": "香蕉",
+ "apple": "苹果",
+ "sandwich": "三明治",
+ "orange": "橙子",
+ "broccoli": "西兰花",
+ "carrot": "胡萝卜",
+ "hot_dog": "热狗",
+ "pizza": "披萨",
+ "donut": "甜甜圈",
+ "cake": "蛋糕",
+ "chair": "椅子",
+ "couch": "沙发",
+ "potted_plant": "盆栽植物",
+ "bed": "床",
+ "mirror": "镜子",
+ "dining_table": "餐桌",
+ "window": "窗户",
+ "desk": "桌子",
+ "toilet": "厕所",
+ "door": "门",
+ "tv": "电视",
+ "laptop": "笔记本电脑",
+ "mouse": "鼠标",
+ "remote": "遥控器",
+ "keyboard": "键盘",
+ "cell_phone": "手机",
+ "microwave": "微波炉",
+ "oven": "烤箱",
+ "toaster": "烤面包机",
+ "sink": "水槽",
+ "refrigerator": "冰箱",
+ "blender": "搅拌机",
+ "book": "书",
+ "clock": "时钟",
+ "vase": "花瓶",
+ "scissors": "剪刀",
+ "teddy_bear": "泰迪熊",
+ "hair_dryer": "吹风机",
+ "toothbrush": "牙刷",
+ "hair_brush": "发刷",
+ "vehicle": "车辆",
+ "squirrel": "松鼠",
+ "deer": "鹿",
+ "animal": "动物",
+ "bark": "树皮",
+ "fox": "狐狸",
+ "goat": "山羊",
+ "rabbit": "兔子",
+ "raccoon": "浣熊",
+ "robot_lawnmower": "自动割草机",
+ "waste_bin": "垃圾桶",
+ "on_demand": "手动",
+ "face": "人脸",
+ "license_plate": "车牌",
+ "package": "包裹",
+ "bbq_grill": "烧烤架",
+ "amazon": "亚马逊",
+ "usps": "美国邮政",
+ "ups": "UPS",
+ "fedex": "联邦快递",
+ "dhl": "DHL",
+ "an_post": "爱尔兰邮政",
+ "purolator": "普罗莱特",
+ "postnl": "荷兰邮政",
+ "nzpost": "新西兰邮政",
+ "postnord": "北欧邮政",
+ "gls": "GLS",
+ "dpd": "DPD"
+}
diff --git a/web/public/locales/zh-CN/views/configEditor.json b/web/public/locales/zh-CN/views/configEditor.json
new file mode 100644
index 000000000..9b37414a4
--- /dev/null
+++ b/web/public/locales/zh-CN/views/configEditor.json
@@ -0,0 +1,15 @@
+{
+ "documentTitle": "配置编辑器 - Frigate",
+ "configEditor": "配置编辑器",
+ "copyConfig": "复制配置",
+ "saveAndRestart": "保存并重启",
+ "saveOnly": "只保存",
+ "toast": {
+ "success": {
+ "copyToClipboard": "配置已复制到剪贴板。"
+ },
+ "error": {
+ "savingError": "保存配置时出错"
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/public/locales/zh-CN/views/events.json b/web/public/locales/zh-CN/views/events.json
new file mode 100644
index 000000000..cc12c9838
--- /dev/null
+++ b/web/public/locales/zh-CN/views/events.json
@@ -0,0 +1,35 @@
+{
+ "alerts": "警告",
+ "detections": "检测",
+ "motion": {
+ "label": "运动",
+ "only": "仅运动画面"
+ },
+ "allCameras": "所有摄像头",
+ "empty": {
+ "alert": "还没有“警告”类回放",
+ "detection": "还没有“探测”类回放",
+ "motion": "还没有运动类数据"
+ },
+ "timeline": "时间线",
+ "timeline.aria": "选择时间线",
+ "events": {
+ "label": "事件",
+ "aria": "选择事件",
+ "noFoundForTimePeriod": "未找到该时间段的事件。"
+ },
+ "documentTitle": "预览 - Frigate",
+ "recordings": {
+ "documentTitle": "回放 - Frigate"
+ },
+ "calendarFilter": {
+ "last24Hours": "过去24小时"
+ },
+ "markAsReviewed": "标记为已审核",
+ "markTheseItemsAsReviewed": "将这些项目标记为已审核",
+ "newReviewItems": {
+ "label": "查看新的审核项目",
+ "button": "新的待审核项目"
+ },
+ "camera": "摄像头"
+}
diff --git a/web/public/locales/zh-CN/views/explore.json b/web/public/locales/zh-CN/views/explore.json
new file mode 100644
index 000000000..e855cb0d9
--- /dev/null
+++ b/web/public/locales/zh-CN/views/explore.json
@@ -0,0 +1,183 @@
+{
+ "documentTitle": "探索 - Frigate",
+ "generativeAI": "生成式 AI",
+ "exploreIsUnavailable": {
+ "title": "探索功能不可用",
+ "embeddingsReindexing": {
+ "context": "跟踪对象嵌入重新索引完成后,可以使用探索功能。",
+ "startingUp": "启动中...",
+ "estimatedTime": "预计剩余时间:",
+ "finishingShortly": "即将完成",
+ "step": {
+ "thumbnailsEmbedded": "缩略图嵌入:",
+ "descriptionsEmbedded": "描述嵌入:",
+ "trackedObjectsProcessed": "跟踪对象已处理:"
+ }
+ },
+ "downloadingModels": {
+ "context": "Frigate正在下载支持语义搜索功能所需的嵌入模型。根据网络连接速度,这可能需要几分钟。",
+ "setup": {
+ "visionModel": "视觉模型",
+ "visionModelFeatureExtractor": "视觉模型特征提取器",
+ "textModel": "文本模型",
+ "textTokenizer": "文本分词器"
+ },
+ "tips": {
+ "context": "模型下载完成后,您可能需要重新索引跟踪对象的嵌入。",
+ "documentation": "阅读文档(英文)"
+ },
+ "error": "发生错误。请检查Frigate日志。"
+ }
+ },
+ "trackedObjectDetails": "跟踪对象详情",
+ "type": {
+ "details": "详情",
+ "snapshot": "快照",
+ "video": "视频",
+ "object_lifecycle": "对象生命周期"
+ },
+ "objectLifecycle": {
+ "title": "对象生命周期",
+ "noImageFound": "未找到此时间戳的图像。",
+ "createObjectMask": "创建对象遮罩",
+ "adjustAnnotationSettings": "调整标注设置",
+ "scrollViewTips": "滚动查看此对象生命周期的重要时刻。",
+ "autoTrackingTips": "自动跟踪摄像头的边界框位置可能不准确。",
+ "lifecycleItemDesc": {
+ "visible": "检测到 {{label}}",
+ "entered_zone": "{{label}} 进入 {{zones}}",
+ "active": "{{label}} 变为活动状态",
+ "stationary": "{{label}} 变为静止状态",
+ "attribute": {
+ "faceOrLicense_plate": "检测到 {{label}} 的 {{attribute}}",
+ "other": "{{label}} 识别为 {{attribute}}"
+ },
+ "gone": "{{label}} 离开",
+ "heard": "听到 {{label}}",
+ "external": "检测到 {{label}}"
+ },
+ "annotationSettings": {
+ "title": "标注设置",
+ "showAllZones": {
+ "title": "显示所有区域",
+ "desc": "在对象进入区域的帧上始终显示区域。"
+ },
+ "offset": {
+ "label": "标注偏移",
+ "desc": "这些数据来自摄像头的检测源,但是叠加在录制源的图像上。这两个流不太可能完全同步。因此,边界框和录像不会完全对齐。但是,可以使用 annotation_offset 字段来调整这个问题。",
+ "documentation": "阅读文档(英文) ",
+ "millisecondsToOffset": "检测标注的偏移毫秒数。默认值:0",
+ "tips": "提示:假设有一个人从左向右走的事件片段。如果事件时间线上的边界框始终在人的左侧,则应该减小该值。同样,如果一个人从左向右走,而边界框始终在人的前面,则应该增加该值。"
+ }
+ },
+ "carousel": {
+ "previous": "上一张",
+ "next": "下一张"
+ }
+ },
+ "details": {
+ "item": {
+ "title": "回放项目详情",
+ "desc": "回放项目详情",
+ "button": {
+ "share": "分享该回放",
+ "viewInExplore": "在探测中查看"
+ },
+ "tips": {
+ "mismatch_one": "检测到 {{count}} 个不可用的对象,并已包含在此审核项中。这些对象可能未达到警告或检测标准,或者已被清理/删除。",
+ "mismatch_other": "检测到 {{count}} 个不可用的对象,并已包含在此审核项中。这些对象可能未达到警告或检测标准,或者已被清理/删除。",
+ "hasMissingObjects": "如果希望 Frigate 保存以下标签的跟踪对象,请调整您的配置:{{objects}}"
+ },
+ "toast": {
+ "success": {
+ "regenerate": "已向 {{provider}} 请求新的描述。根据提供商的速度,生成新描述可能需要一些时间。",
+ "updatedSublabel": "成功更新子标签。"
+ },
+ "error": {
+ "regenerate": "调用 {{provider}} 生成新描述失败:{{errorMessage}}",
+ "updatedSublabelFailed": "更新子标签失败:{{errorMessage}}"
+ }
+ }
+ },
+ "label": "标签",
+ "editSubLabel": {
+ "title": "编辑子标签",
+ "desc": "为 {{label}} 输入新的子标签",
+ "descNoLabel": "为此跟踪对象输入新的子标签"
+ },
+ "topScore": {
+ "label": "最高得分",
+ "info": "最高分是跟踪对象的最高中位数得分,因此可能与搜索结果缩略图上显示的得分不同。"
+ },
+ "estimatedSpeed": "预计速度",
+ "objects": "对象",
+ "camera": "摄像头",
+ "zones": "区域",
+ "timestamp": "时间",
+ "button": {
+ "findSimilar": "查找相似项",
+ "regenerate": {
+ "title": "重新生成",
+ "label": "重新生成跟踪对象描述"
+ }
+ },
+ "description": {
+ "label": "描述",
+ "placeholder": "跟踪对象的描述",
+ "aiTips": "在跟踪对象的生命周期结束之前,Frigate 不会向您的生成式 AI 提供商请求描述。"
+ },
+ "expandRegenerationMenu": "展开重新生成菜单",
+ "regenerateFromSnapshot": "从快照重新生成",
+ "regenerateFromThumbnails": "从缩略图重新生成",
+ "tips": {
+ "descriptionSaved": "已保存描述",
+ "saveDescriptionFailed": "更新描述失败:{{errorMessage}}"
+ }
+ },
+ "itemMenu": {
+ "downloadVideo": {
+ "label": "下载视频",
+ "aria": "下载视频"
+ },
+ "downloadSnapshot": {
+ "label": "下载快照",
+ "aria": "下载快照"
+ },
+ "viewObjectLifecycle": {
+ "label": "查看对象生命周期",
+ "aria": "显示对象的生命周期"
+ },
+ "findSimilar": {
+ "label": "查找相似项",
+ "aria": "查看相似的对象"
+ },
+ "submitToPlus": {
+ "label": "提交至 Frigate+",
+ "aria": "提交至 Frigate Plus"
+ },
+ "viewInHistory": {
+ "label": "在历史记录中查看",
+ "aria": "在历史记录中查看"
+ },
+ "deleteTrackedObject": {
+ "label": "删除此跟踪对象"
+ }
+ },
+ "dialog": {
+ "confirmDelete": {
+ "title": "确认删除",
+ "desc": "删除此跟踪对象将移除快照、所有已保存的嵌入数据以及任何关联的对象生命周期条目。但在历史视图中的录制视频不会被删除。mode: {{effectiveRetainMode}},因此此按需录制将仅保留包含 {{effectiveRetainModeName}} 的片段。"
+ },
+ "editLayout": {
+ "label": "编辑布局",
+ "group": {
+ "label": "编辑摄像机分组"
+ },
+ "exitEdit": "退出编辑"
+ }
+}
diff --git a/web/public/locales/zh-CN/views/recording.json b/web/public/locales/zh-CN/views/recording.json
new file mode 100644
index 000000000..37cab2514
--- /dev/null
+++ b/web/public/locales/zh-CN/views/recording.json
@@ -0,0 +1,12 @@
+{
+ "export": "导出",
+ "calendar": "日历",
+ "filter": "筛选",
+ "filters": "筛选条件",
+ "toast": {
+ "error": {
+ "noValidTimeSelected": "未选择有效的时间范围",
+ "endTimeMustAfterStartTime": "结束时间必须晚于开始时间"
+ }
+ }
+}
diff --git a/web/public/locales/zh-CN/views/search.json b/web/public/locales/zh-CN/views/search.json
new file mode 100644
index 000000000..d55a611b9
--- /dev/null
+++ b/web/public/locales/zh-CN/views/search.json
@@ -0,0 +1,67 @@
+{
+ "search": "搜索",
+ "savedSearches": "已保存的搜索",
+ "searchFor": "搜索 {{inputValue}}",
+ "button": {
+ "clear": "清除搜索",
+ "save": "保存搜索",
+ "delete": "删除已保存的搜索",
+ "filterInformation": "筛选信息",
+ "filterActive": "筛选器已激活"
+ },
+ "trackedObjectId": "跟踪对象 ID",
+ "filter": {
+ "label": {
+ "cameras": "摄像机",
+ "labels": "标签",
+ "zones": "区域",
+ "sub_labels": "子标签",
+ "search_type": "搜索类型",
+ "time_range": "时间范围",
+ "before": "之前",
+ "after": "之后",
+ "min_score": "最低分数",
+ "max_score": "最高分数",
+ "min_speed": "最低速度",
+ "max_speed": "最高速度",
+ "recognized_license_plate": "识别的车牌",
+ "has_clip": "包含片段",
+ "has_snapshot": "包含快照"
+ },
+ "searchType": {
+ "thumbnail": "缩略图",
+ "description": "描述"
+ },
+ "toast": {
+ "error": {
+ "beforeDateBeLaterAfter": "结束日期必须晚于开始日期。",
+ "afterDatebeEarlierBefore": "开始日期必须早于结束日期。",
+ "minScoreMustBeLessOrEqualMaxScore": "最低分数必须小于或等于最高分数。",
+ "maxScoreMustBeGreaterOrEqualMinScore": "最高分数必须大于或等于最低分数。",
+ "minSpeedMustBeLessOrEqualMaxSpeed": "最低速度必须小于或等于最高速度。",
+ "maxSpeedMustBeGreaterOrEqualMinSpeed": "最高速度必须大于或等于最低速度。"
+ }
+ },
+ "tips": {
+ "title": "如何使用文本筛选器(英文)",
+ "desc": {
+ "text": "筛选器可帮助您缩小搜索范围。注意,目前还暂不支持中文搜索。以下是在输入字段中使用筛选器的方法:",
+ "step": "cameras:front_door label:person before:01012024 time_range:3:00PM-4:00PM"
+ }
+ },
+ "header": {
+ "currentFilterType": "筛选值",
+ "noFilters": "筛选条件",
+ "activeFilters": "激活的筛选项"
+ }
+ },
+ "similaritySearch": {
+ "title": "相似搜索",
+ "active": "相似搜索已激活",
+ "clear": "清除相似搜索"
+ },
+ "placeholder": {
+ "search": "搜索..."
+ }
+}
diff --git a/web/public/locales/zh-CN/views/settings.json b/web/public/locales/zh-CN/views/settings.json
new file mode 100644
index 000000000..ccef8f151
--- /dev/null
+++ b/web/public/locales/zh-CN/views/settings.json
@@ -0,0 +1,550 @@
+{
+ "documentTitle": {
+ "default": "设置 - Frigate",
+ "authentication": "身份验证设置 - Frigate",
+ "camera": "摄像头设置 - Frigate",
+ "classification": "分类设置 - Frigate",
+ "masksAndZones": "遮罩和区域编辑器 - Frigate",
+ "motionTuner": "运动调整器 - Frigate",
+ "object": "对象设置 - Frigate",
+ "general": "常规设置 - Frigate"
+ },
+ "dialog": {
+ "unsavedChanges": {
+ "title": "你有未保存的更改。",
+ "desc": "是否要在继续之前保存更改?"
+ }
+ },
+ "menu": {
+ "uiSettings": "界面设置",
+ "classificationSettings": "分类设置",
+ "cameraSettings": "摄像头设置",
+ "masksAndZones": "遮罩/ 区域",
+ "motionTuner": "运动调整器",
+ "debug": "调试",
+ "users": "用户",
+ "notifications": "通知"
+ },
+ "cameraSetting": {
+ "camera": "摄像头",
+ "noCamera": "没有摄像头"
+ },
+ "general": {
+ "title": "常规设置",
+ "liveDashboard": {
+ "title": "实时监控面板",
+ "automaticLiveView": {
+ "label": "自动实时预览",
+ "desc": "检测到画面活动时将自动切换至该摄像头实时画面。禁用此选项会导致实时监控页面的摄像头图像每分钟只更新一次。"
+ },
+ "playAlertVideos": {
+ "label": "播放警告视频",
+ "desc": "默认情况下,实时监控页面上的最新警告会以一小段循环的形式进行播放。禁用此选项将仅显示浏览器本地缓存的静态图片。"
+ }
+ },
+ "storedLayouts": {
+ "title": "存储监控面板布局",
+ "desc": "可以在监控面板调整或拖动摄像头的布局。这些设置将保存在浏览器的本地存储中。",
+ "clearAll": "清除所有布局"
+ },
+ "cameraGroupStreaming": {
+ "title": "摄像头组视频流设置",
+ "desc": "每个摄像头组的视频流设置将保存在浏览器的本地存储中。",
+ "clearAll": "清除所有视频流设置"
+ },
+ "recordingsViewer": {
+ "title": "回放查看",
+ "defaultPlaybackRate": {
+ "label": "默认播放速率",
+ "desc": "调整播放录像时默认的速率。"
+ }
+ },
+ "calendar": {
+ "title": "日历",
+ "firstWeekday": {
+ "label": "每周第一天",
+ "desc": "设置每周第一天是星期几。",
+ "sunday": "星期天",
+ "monday": "星期一"
+ }
+ },
+ "toast": {
+ "success": {
+ "clearStoredLayout": "已清除 {{cameraName}} 的存储布局",
+ "clearStreamingSettings": "已清除所有摄像头组的视频流设置。"
+ },
+ "error": {
+ "clearStoredLayoutFailed": "清除存储布局失败:{{errorMessage}}",
+ "clearStreamingSettingsFailed": "清除视频流设置失败:{{errorMessage}}"
+ }
+ }
+ },
+ "classification": {
+ "title": "分类设置",
+ "semanticSearch": {
+ "title": "语义搜索",
+ "desc": "Frigate的语义搜索能够让你使用自然语言根据图像本身、自定义的文本描述或自动生成的描述来搜索视频。",
+ "readTheDocumentation": "阅读文档(英文)",
+ "reindexOnStartup": {
+ "label": "启动时重新索引",
+ "desc": "每次启动将重新索引并重新处理所有缩略图和描述。关闭该设置后不要忘记重启!"
+ },
+ "modelSize": {
+ "label": "模型大小",
+ "desc": "用于语义搜索的语言模型大小",
+ "small": {
+ "title": "小",
+ "desc": "使用 小模型。该模型将使用较少的内存,在CPU上也能较快的运行。质量较好。"
+ },
+ "large": {
+ "title": "大",
+ "desc": "使用 大模型。该模型采用了完整的Jina模型,并在适用的情况下使用GPU。"
+ }
+ }
+ },
+ "faceRecognition": {
+ "title": "人脸识别",
+ "desc": "人脸识别功能允许为人物分配名称,当识别到他们的面孔时,Frigate 会将人物的名字作为子标签进行分配。这些信息会显示在界面、过滤器以及通知中。",
+ "readTheDocumentation": "阅读文档(英文)"
+ },
+ "licensePlateRecognition": {
+ "title": "车牌识别",
+ "desc": "Frigate 可以识别车辆的车牌,并自动将检测到的字符添加到 recognized_license_plate 字段中,或将已知名称作为子标签添加到汽车类型的对象中。常见的使用场景可能是读取驶入车道的汽车车牌或经过街道的汽车车牌。",
+ "readTheDocumentation": "阅读文档(英文)"
+ },
+ "toast": {
+ "success": "分类设置已保存。",
+ "error": "保存配置更改失败:{{errorMessage}}"
+ }
+ },
+ "camera": {
+ "title": "摄像头设置",
+ "streams": {
+ "title": "视频流",
+ "desc": "禁用摄像头将完全停止 Frigate 对该摄像头视频流的处理。检测、录制和调试功能都将不可用。运动区域框
将在当前检测到运动的区域内显示红色区域框。
" + }, + "regions": { + "title": "范围", + "desc": "显示发送到运动检测器感兴趣范围的框。", + "tips": "范围框
将在帧中发送到目标检测器的感兴趣范围上叠加绿色框。
" + }, + "objectShapeFilterDrawing": { + "title": "允许绘制“对象形状过滤器”", + "desc": "在图像上绘制矩形,以查看区域和比例详细信息。", + "tips": "启用此选项,能够在摄像头图像上绘制矩形,将显示其区域和比例。然后,您可以使用这些值在配置中设置对象形状过滤器参数。", + "document": "阅读文档(英文)", + "score": "分数", + "ratio": "比例", + "area": "区域" + } + }, + "users": { + "title": "用户", + "management": { + "title": "用户管理", + "desc": "管理此 Frigate 实例的用户账户。" + }, + "addUser": "添加用户", + "updatePassword": "修改密码", + "toast": { + "success": { + "createUser": "用户 {{user}} 创建成功", + "deleteUser": "用户 {{user}} 删除成功", + "updatePassword": "已成功修改密码", + "roleUpdated": "已更新 {{user}} 的权限组" + }, + "error": { + "setPasswordFailed": "保存密码出现错误:{{errorMessage}}", + "createUserFailed": "创建用户失败:{{errorMessage}}", + "deleteUserFailed": "删除用户失败:{{errorMessage}}", + "roleUpdateFailed": "更新权限组失败:{{errorMessage}}" + } + }, + "table": { + "username": "用户名", + "actions": "操作", + "role": "权限组", + "noUsers": "未找到用户。", + "changeRole": "更改用户角色", + "password": "密码", + "deleteUser": "删除用户" + }, + "dialog": { + "form": { + "user": { + "title": "用户名", + "desc": "仅允许使用字母、数字、句点和下划线。", + "placeholder": "请输入用户名" + }, + "password": { + "title": "密码", + "placeholder": "请输入密码", + "confirm": { + "title": "确认密码", + "placeholder": "请再次输入密码" + }, + "strength": { + "title": "密码强度:", + "weak": "弱", + "medium": "中等", + "strong": "强", + "veryStrong": "非常强" + }, + "match": "密码匹配", + "notMatch": "密码不匹配" + }, + "newPassword": { + "title": "新密码", + "placeholder": "请输入新密码", + "confirm": { + "placeholder": "请再次输入新密码" + } + }, + "usernameIsRequired": "用户名为必填项" + }, + "createUser": { + "title": "创建新用户", + "desc": "创建一个新用户账户,并指定一个角色以控制访问 Frigate UI 的权限。", + "usernameOnlyInclude": "用户名只能包含字母、数字和 _" + }, + "deleteUser": { + "title": "删除该用户", + "desc": "此操作无法撤销。这将永久删除用户账户并移除所有相关数据。", + "warn": "你确定要删除 {{username}} 吗?" + }, + "passwordSetting": { + "updatePassword": "更新 {{username}} 的密码", + "setPassword": "设置密码", + "desc": "创建一个强密码来保护此账户。" + }, + "changeRole": { + "title": "更改用户权限组", + "desc": "更新 {{username}} 的权限", + "roleInfo": "请选择此用户的适当角色:
https://...)。这是浏览器的限制。请通过安全方式访问 Frigate 以使用通知功能。",
+ "documentation": "阅读文档(英文)"
+ },
+ "email": {
+ "title": "电子邮箱",
+ "placeholder": "例如:example@email.com",
+ "desc": "需要输入有效的电子邮件,在推送服务出现问题时,将使用此电子邮件进行通知。"
+ },
+ "cameras": {
+ "title": "摄像头",
+ "noCameras": "没有可用的摄像头",
+ "desc": "选择要启用通知的摄像头。"
+ },
+ "deviceSpecific": "设备专用设置",
+ "registerDevice": "注册该设备",
+ "unregisterDevice": "取消注册该设备",
+ "sendTestNotification": "发送测试通知",
+ "active": "通知已启用",
+ "suspended": "通知已暂停 {{time}}",
+ "suspendTime": {
+ "5minutes": "暂停 5 分钟",
+ "10minutes": "暂停 10 分钟",
+ "30minutes": "暂停 30 分钟",
+ "1hour": "暂停 1 小时",
+ "12hours": "暂停 12 小时",
+ "24hours": "暂停 24 小时",
+ "untilRestart": "暂停直到重启"
+ },
+ "cancelSuspension": "取消暂停",
+ "toast": {
+ "success": {
+ "registered": "已成功注册通知。需要重启 Frigate 才能发送任何通知(包括测试通知)。",
+ "settingSaved": "通知设置已保存。"
+ },
+ "error": {
+ "registerFailed": "通知注册失败。"
+ }
+ }
+ },
+ "frigatePlus": {
+ "title": "Frigate+ 设置",
+ "apiKey": {
+ "title": "Frigate+ API 密钥",
+ "validated": "Frigate+ API 密钥已检测并验证通过",
+ "notValidated": "未检测到 Frigate+ API 密钥或验证未通过",
+ "desc": "Frigate+ API 密钥用于启用与 Frigate+ 服务的集成。",
+ "plusLink": "了解更多关于 Frigate+"
+ },
+ "snapshotConfig": {
+ "title": "快照配置",
+ "desc": "提交到 Frigate+ 需要同时在配置中启用快照和 clean_copy 快照。",
+ "documentation": "阅读文档",
+ "cleanCopyWarning": "部分摄像头已启用快照但未启用 clean_copy。您需要在快照配置中启用 clean_copy,才能将这些摄像头的图像提交到 Frigate+。",
+ "table": {
+ "camera": "摄像头",
+ "snapshots": "快照",
+ "cleanCopySnapshots": "clean_copy 快照"
+ }
+ },
+ "modelInfo": {
+ "title": "模型信息",
+ "modelType": "模型类型",
+ "trainDate": "训练日期",
+ "baseModel": "基础模型",
+ "supportedDetectors": "支持的检测器",
+ "cameras": "摄像头",
+ "loading": "正在加载模型信息...",
+ "error": "加载模型信息失败"
+ }
+ }
+}
diff --git a/web/public/locales/zh-CN/views/system.json b/web/public/locales/zh-CN/views/system.json
new file mode 100644
index 000000000..01251f3c5
--- /dev/null
+++ b/web/public/locales/zh-CN/views/system.json
@@ -0,0 +1,156 @@
+{
+ "documentTitle": {
+ "cameras": "摄像头统计 - Frigate",
+ "storage": "存储统计 - Frigate",
+ "general": "常规统计 - Frigate",
+ "features": "功能统计 - Frigate",
+ "logs": {
+ "frigate": "Frigate 日志 - Frigate",
+ "go2rtc": "Go2RTC 日志 - Frigate",
+ "nginx": "Nginx 日志 - Frigate"
+ }
+ },
+ "title": "系统",
+ "metrics": "系统指标",
+ "logs": {
+ "download": {
+ "label": "下载日志"
+ },
+ "copy": {
+ "label": "复制到剪贴板",
+ "success": "已复制日志到剪贴板",
+ "error": "无法复制日志到剪贴板"
+ },
+ "type": {
+ "label": "类型",
+ "timestamp": "时间戳",
+ "tag": "标签",
+ "message": "消息"
+ },
+ "tips": "日志正在从服务器流式传输",
+ "toast": {
+ "error": {
+ "fetchingLogsFailed": "获取日志出错:{{errorMessage}}",
+ "whileStreamingLogs": "流式传输日志时出错:{{errorMessage}}"
+ }
+ }
+ },
+ "general": {
+ "title": "常规",
+ "detector": {
+ "title": "探测器",
+ "inferenceSpeed": "探测器推理速度",
+ "cpuUsage": "探测器CPU使用率",
+ "memoryUsage": "探测器内存使用率"
+ },
+ "hardwareInfo": {
+ "title": "硬件信息",
+ "gpuUsage": "GPU使用率",
+ "gpuMemory": "GPU显存",
+ "gpuEncoder": "GPU编码",
+ "gpuDecoder": "GPU解码",
+ "gpuInfo": {
+ "vainfoOutput": {
+ "title": "Vainfo 输出",
+ "returnCode": "返回代码:{{code}}",
+ "processOutput": "进程输出:",
+ "processError": "进程错误:"
+ },
+ "nvidiaSMIOutput": {
+ "title": "Nvidia SMI 输出",
+ "name": "名称:{{name}}",
+ "driver": "驱动:{{driver}}",
+ "cudaComputerCapability": "CUDA计算能力:{{cuda_compute}}",
+ "vbios": "VBios信息:{{vbios}}"
+ },
+ "closeInfo": {
+ "label": "关闭GPU信息"
+ },
+ "copyInfo": {
+ "label": "复制GPU信息"
+ },
+ "toast": {
+ "success": "已复制GPU信息到剪贴板"
+ }
+ }
+ },
+ "otherProcesses": {
+ "title": "其他进程",
+ "processCpuUsage": "主进程CPU使用率",
+ "processMemoryUsage": "主进程内存使用率"
+ }
+ },
+ "storage": {
+ "title": "存储",
+ "overview": "概览",
+ "recordings": {
+ "title": "录制内容",
+ "tips": "该值表示 Frigate 数据库中录制内容所使用的总存储空间。Frigate 不会追踪磁盘上所有文件的存储使用情况。",
+ "earliestRecording": "最早的可用录制:"
+ },
+ "cameraStorage": {
+ "title": "摄像头存储",
+ "camera": "摄像头",
+ "unusedStorageInformation": "未使用存储信息",
+ "storageUsed": "存储使用",
+ "percentageOfTotalUsed": "总使用率",
+ "bandwidth": "带宽",
+ "unused": {
+ "title": "未使用",
+ "tips": "如果您的驱动器上存储了除 Frigate 录制内容之外的其他文件,该值可能无法准确反映 Frigate 可用的剩余空间。Frigate 不会追踪录制内容以外的存储使用情况。"
+ }
+ }
+ },
+ "cameras": {
+ "title": "摄像头",
+ "overview": "概览",
+ "info": {
+ "cameraProbeInfo": "{{camera}} 的摄像头信息",
+ "streamDataFromFFPROBE": "流数据信息通过ffprobe获取。",
+ "fetching": "正在获取摄像头数据",
+ "stream": "视频流{{idx}}",
+ "video": "视频:",
+ "codec": "编解码器:",
+ "resolution": "分辨率:",
+ "fps": "帧率:",
+ "unknown": "未知",
+ "audio": "音频:",
+ "error": "错误:{{error}}",
+ "tips": {
+ "title": "摄像头信息"
+ }
+ },
+ "framesAndDetections": "帧数/检测次数",
+ "label": {
+ "camera": "摄像头",
+ "detect": "探测",
+ "skipped": "跳过",
+ "ffmpeg": "ffmpeg编码器",
+ "capture": "捕获"
+ },
+ "toast": {
+ "success": {
+ "copyToClipboard": "已复制探测数据到剪贴板。"
+ },
+ "error": {
+ "unableToProbeCamera": "无法探测摄像头:{{errorMessage}}"
+ }
+ }
+ },
+ "lastRefreshed": "最后刷新时间:",
+ "stats": {
+ "ffmpegHighCpuUsage": "{{camera}} 的 FFMPEG CPU 使用率较高({{ffmpegAvg}}%)",
+ "detectHighCpuUsage": "{{camera}} 的 探测 CPU 使用率较高({{detectAvg}}%)",
+ "healthy": "系统运行正常",
+ "reindexingEmbeddings": "正在重新索引嵌入(已完成 {{processed}}%)"
+ },
+ "features": {
+ "title": "功能",
+ "embeddings": {
+ "image_embedding_speed": "图像特征提取速度",
+ "face_embedding_speed": "人脸特征提取速度",
+ "plate_recognition_speed": "车牌识别速度",
+ "text_embedding_speed": "文本编码速度"
+ }
+ }
+}
diff --git a/web/src/api/ws.tsx b/web/src/api/ws.tsx
index 5eedcdbcd..3e9c8c14f 100644
--- a/web/src/api/ws.tsx
+++ b/web/src/api/ws.tsx
@@ -44,7 +44,8 @@ function useValue(): useValueReturn {
return;
}
- const cameraActivity: { [key: string]: object } = JSON.parse(activityValue);
+ const cameraActivity: { [key: string]: FrigateCameraState } =
+ JSON.parse(activityValue);
if (Object.keys(cameraActivity).length === 0) {
return;
@@ -64,9 +65,7 @@ function useValue(): useValueReturn {
autotracking,
alerts,
detections,
- } =
- // @ts-expect-error we know this is correct
- state["config"];
+ } = state["config"];
cameraStates[`${name}/recordings/state`] = record ? "ON" : "OFF";
cameraStates[`${name}/enabled/state`] = enabled ? "ON" : "OFF";
cameraStates[`${name}/detect/state`] = detect ? "ON" : "OFF";
@@ -174,7 +173,7 @@ export function useEnabledState(camera: string): {
value: { payload },
send,
} = useWs(`${camera}/enabled/state`, `${camera}/enabled/set`);
- return { payload: (payload ?? "ON") as ToggleableSetting, send };
+ return { payload: payload as ToggleableSetting, send };
}
export function useDetectState(camera: string): {
diff --git a/web/src/components/Statusbar.tsx b/web/src/components/Statusbar.tsx
index 1b20b26f6..2b03b750d 100644
--- a/web/src/components/Statusbar.tsx
+++ b/web/src/components/Statusbar.tsx
@@ -5,12 +5,16 @@ import {
} from "@/context/statusbar-provider";
import useStats, { useAutoFrigateStats } from "@/hooks/use-stats";
import { useContext, useEffect, useMemo } from "react";
+import { useTranslation } from "react-i18next";
+
import { FaCheck } from "react-icons/fa";
import { IoIosWarning } from "react-icons/io";
import { MdCircle } from "react-icons/md";
import { Link } from "react-router-dom";
export default function Statusbar() {
+ const { t } = useTranslation(["views/system"]);
+
const { messages, addMessage, clearMessages } = useContext(
StatusBarMessagesContext,
)!;
@@ -50,14 +54,19 @@ export default function Statusbar() {
clearMessages("embeddings-reindex");
addMessage(
"embeddings-reindex",
- `Reindexing embeddings (${Math.floor((reindexState.processed_objects / reindexState.total_objects) * 100)}% complete)`,
+ t("stats.reindexingEmbeddings", {
+ processed: Math.floor(
+ (reindexState.processed_objects / reindexState.total_objects) *
+ 100,
+ ),
+ }),
);
}
if (reindexState.status === "completed") {
clearMessages("embeddings-reindex");
}
}
- }, [reindexState, addMessage, clearMessages]);
+ }, [reindexState, addMessage, clearMessages, t]);
return (