diff --git a/generate_config_translations.py b/generate_config_translations.py new file mode 100644 index 000000000..c19578f1a --- /dev/null +++ b/generate_config_translations.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +""" +Generate English translation JSON files from Pydantic config models. + +This script dynamically extracts all top-level config sections from FrigateConfig +and generates JSON translation files with titles and descriptions for the web UI. +""" + +import json +import logging +import shutil +from pathlib import Path +from typing import Any, Dict, Optional, get_args, get_origin + +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from frigate.config.config import FrigateConfig + +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +def get_field_translations(field_info: FieldInfo) -> Dict[str, str]: + """Extract title and description from a Pydantic field.""" + translations = {} + + if field_info.title: + translations["label"] = field_info.title + + if field_info.description: + translations["description"] = field_info.description + + return translations + + +def process_model_fields(model: type[BaseModel]) -> Dict[str, Any]: + """ + Recursively process a Pydantic model to extract translations. + + Returns a nested dictionary structure matching the config schema, + with title and description for each field. + """ + translations = {} + + model_fields = model.model_fields + + for field_name, field_info in model_fields.items(): + field_translations = get_field_translations(field_info) + + # Get the field's type annotation + field_type = field_info.annotation + + # Handle Optional types + origin = get_origin(field_type) + + if origin is Optional or ( + hasattr(origin, "__name__") and origin.__name__ == "UnionType" + ): + args = get_args(field_type) + field_type = next( + (arg for arg in args if arg is not type(None)), field_type + ) + + # Handle Dict types (like Dict[str, CameraConfig]) + if get_origin(field_type) is dict: + dict_args = get_args(field_type) + + if len(dict_args) >= 2: + value_type = dict_args[1] + + if isinstance(value_type, type) and issubclass(value_type, BaseModel): + nested_translations = process_model_fields(value_type) + + if nested_translations: + field_translations["properties"] = nested_translations + elif isinstance(field_type, type) and issubclass(field_type, BaseModel): + nested_translations = process_model_fields(field_type) + if nested_translations: + field_translations["properties"] = nested_translations + + if field_translations: + translations[field_name] = field_translations + + return translations + + +def generate_section_translation( + section_name: str, field_info: FieldInfo +) -> Dict[str, Any]: + """ + Generate translation structure for a top-level config section. + """ + section_translations = get_field_translations(field_info) + field_type = field_info.annotation + origin = get_origin(field_type) + + if origin is Optional or ( + hasattr(origin, "__name__") and origin.__name__ == "UnionType" + ): + args = get_args(field_type) + field_type = next((arg for arg in args if arg is not type(None)), field_type) + + # Handle Dict types (like detectors, cameras, camera_groups) + if get_origin(field_type) is dict: + dict_args = get_args(field_type) + if len(dict_args) >= 2: + value_type = dict_args[1] + if isinstance(value_type, type) and issubclass(value_type, BaseModel): + nested = process_model_fields(value_type) + if nested: + section_translations["properties"] = nested + + # If the field itself is a BaseModel, process it + elif isinstance(field_type, type) and issubclass(field_type, BaseModel): + nested = process_model_fields(field_type) + if nested: + section_translations["properties"] = nested + + return section_translations + + +def main(): + """Main function to generate config translations.""" + + # Define output directory + output_dir = Path(__file__).parent / "web" / "public" / "locales" / "en" / "config" + + logger.info(f"Output directory: {output_dir}") + + # Clean and recreate the output directory + if output_dir.exists(): + logger.info(f"Removing existing directory: {output_dir}") + shutil.rmtree(output_dir) + + logger.info(f"Creating directory: {output_dir}") + output_dir.mkdir(parents=True, exist_ok=True) + + config_fields = FrigateConfig.model_fields + logger.info(f"Found {len(config_fields)} top-level config sections") + + for field_name, field_info in config_fields.items(): + if field_name.startswith("_"): + continue + + logger.info(f"Processing section: {field_name}") + section_data = generate_section_translation(field_name, field_info) + + if not section_data: + logger.warning(f"No translations found for section: {field_name}") + continue + + output_file = output_dir / f"{field_name}.json" + with open(output_file, "w", encoding="utf-8") as f: + json.dump(section_data, f, indent=2, ensure_ascii=False) + + logger.info(f"Generated: {output_file}") + + logger.info("Translation generation complete!") + + +if __name__ == "__main__": + main() diff --git a/web/public/locales/en/config/audio.json b/web/public/locales/en/config/audio.json new file mode 100644 index 000000000..f9aaffa6b --- /dev/null +++ b/web/public/locales/en/config/audio.json @@ -0,0 +1,26 @@ +{ + "label": "Global Audio events configuration.", + "properties": { + "enabled": { + "label": "Enable audio events." + }, + "max_not_heard": { + "label": "Seconds of not hearing the type of audio to end the event." + }, + "min_volume": { + "label": "Min volume required to run audio detection." + }, + "listen": { + "label": "Audio to listen for." + }, + "filters": { + "label": "Audio filters." + }, + "enabled_in_config": { + "label": "Keep track of original state of audio detection." + }, + "num_threads": { + "label": "Number of detection threads" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/audio_transcription.json b/web/public/locales/en/config/audio_transcription.json new file mode 100644 index 000000000..6922b9d80 --- /dev/null +++ b/web/public/locales/en/config/audio_transcription.json @@ -0,0 +1,23 @@ +{ + "label": "Audio transcription config.", + "properties": { + "enabled": { + "label": "Enable audio transcription." + }, + "language": { + "label": "Language abbreviation to use for audio event transcription/translation." + }, + "device": { + "label": "The device used for license plate recognition." + }, + "model_size": { + "label": "The size of the embeddings model used." + }, + "enabled_in_config": { + "label": "Keep track of original state of camera." + }, + "live_enabled": { + "label": "Enable live transcriptions." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/auth.json b/web/public/locales/en/config/auth.json new file mode 100644 index 000000000..a524d8d1b --- /dev/null +++ b/web/public/locales/en/config/auth.json @@ -0,0 +1,35 @@ +{ + "label": "Auth configuration.", + "properties": { + "enabled": { + "label": "Enable authentication" + }, + "reset_admin_password": { + "label": "Reset the admin password on startup" + }, + "cookie_name": { + "label": "Name for jwt token cookie" + }, + "cookie_secure": { + "label": "Set secure flag on cookie" + }, + "session_length": { + "label": "Session length for jwt session tokens" + }, + "refresh_time": { + "label": "Refresh the session if it is going to expire in this many seconds" + }, + "failed_login_rate_limit": { + "label": "Rate limits for failed login attempts." + }, + "trusted_proxies": { + "label": "Trusted proxies for determining IP address to rate limit" + }, + "hash_iterations": { + "label": "Password hash iterations" + }, + "roles": { + "label": "Role to camera mappings. Empty list grants access to all cameras." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/birdseye.json b/web/public/locales/en/config/birdseye.json new file mode 100644 index 000000000..f122f314c --- /dev/null +++ b/web/public/locales/en/config/birdseye.json @@ -0,0 +1,37 @@ +{ + "label": "Birdseye configuration.", + "properties": { + "enabled": { + "label": "Enable birdseye view." + }, + "mode": { + "label": "Tracking mode." + }, + "restream": { + "label": "Restream birdseye via RTSP." + }, + "width": { + "label": "Birdseye width." + }, + "height": { + "label": "Birdseye height." + }, + "quality": { + "label": "Encoding quality." + }, + "inactivity_threshold": { + "label": "Birdseye Inactivity Threshold" + }, + "layout": { + "label": "Birdseye Layout Config", + "properties": { + "scaling_factor": { + "label": "Birdseye Scaling Factor" + }, + "max_cameras": { + "label": "Max cameras" + } + } + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/camera_groups.json b/web/public/locales/en/config/camera_groups.json new file mode 100644 index 000000000..2900e9c67 --- /dev/null +++ b/web/public/locales/en/config/camera_groups.json @@ -0,0 +1,14 @@ +{ + "label": "Camera group configuration", + "properties": { + "cameras": { + "label": "List of cameras in this group." + }, + "icon": { + "label": "Icon that represents camera group." + }, + "order": { + "label": "Sort order for group." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/cameras.json b/web/public/locales/en/config/cameras.json new file mode 100644 index 000000000..67015bde5 --- /dev/null +++ b/web/public/locales/en/config/cameras.json @@ -0,0 +1,761 @@ +{ + "label": "Camera configuration.", + "properties": { + "name": { + "label": "Camera name." + }, + "friendly_name": { + "label": "Camera friendly name used in the Frigate UI." + }, + "enabled": { + "label": "Enable camera." + }, + "audio": { + "label": "Audio events configuration.", + "properties": { + "enabled": { + "label": "Enable audio events." + }, + "max_not_heard": { + "label": "Seconds of not hearing the type of audio to end the event." + }, + "min_volume": { + "label": "Min volume required to run audio detection." + }, + "listen": { + "label": "Audio to listen for." + }, + "filters": { + "label": "Audio filters." + }, + "enabled_in_config": { + "label": "Keep track of original state of audio detection." + }, + "num_threads": { + "label": "Number of detection threads" + } + } + }, + "audio_transcription": { + "label": "Audio transcription config.", + "properties": { + "enabled": { + "label": "Enable audio transcription." + }, + "language": { + "label": "Language abbreviation to use for audio event transcription/translation." + }, + "device": { + "label": "The device used for license plate recognition." + }, + "model_size": { + "label": "The size of the embeddings model used." + }, + "enabled_in_config": { + "label": "Keep track of original state of camera." + }, + "live_enabled": { + "label": "Enable live transcriptions." + } + } + }, + "birdseye": { + "label": "Birdseye camera configuration.", + "properties": { + "enabled": { + "label": "Enable birdseye view for camera." + }, + "mode": { + "label": "Tracking mode for camera." + }, + "order": { + "label": "Position of the camera in the birdseye view." + } + } + }, + "detect": { + "label": "Object detection configuration.", + "properties": { + "enabled": { + "label": "Detection Enabled." + }, + "height": { + "label": "Height of the stream for the detect role." + }, + "width": { + "label": "Width of the stream for the detect role." + }, + "fps": { + "label": "Number of frames per second to process through detection." + }, + "min_initialized": { + "label": "Minimum number of consecutive hits for an object to be initialized by the tracker." + }, + "max_disappeared": { + "label": "Maximum number of frames the object can disappear before detection ends." + }, + "stationary": { + "label": "Stationary objects config.", + "properties": { + "interval": { + "label": "Frame interval for checking stationary objects." + }, + "threshold": { + "label": "Number of frames without a position change for an object to be considered stationary" + }, + "max_frames": { + "label": "Max frames for stationary objects.", + "properties": { + "default": { + "label": "Default max frames." + }, + "objects": { + "label": "Object specific max frames." + } + } + }, + "classifier": { + "label": "Enable visual classifier for determing if objects with jittery bounding boxes are stationary." + } + } + }, + "annotation_offset": { + "label": "Milliseconds to offset detect annotations by." + } + } + }, + "face_recognition": { + "label": "Face recognition config.", + "properties": { + "enabled": { + "label": "Enable face recognition." + }, + "min_area": { + "label": "Min area of face box to consider running face recognition." + } + } + }, + "ffmpeg": { + "label": "FFmpeg configuration for the camera.", + "properties": { + "path": { + "label": "FFmpeg path" + }, + "global_args": { + "label": "Global FFmpeg arguments." + }, + "hwaccel_args": { + "label": "FFmpeg hardware acceleration arguments." + }, + "input_args": { + "label": "FFmpeg input arguments." + }, + "output_args": { + "label": "FFmpeg output arguments per role.", + "properties": { + "detect": { + "label": "Detect role FFmpeg output arguments." + }, + "record": { + "label": "Record role FFmpeg output arguments." + } + } + }, + "retry_interval": { + "label": "Time in seconds to wait before FFmpeg retries connecting to the camera." + }, + "apple_compatibility": { + "label": "Set tag on HEVC (H.265) recording stream to improve compatibility with Apple players." + }, + "inputs": { + "label": "Camera inputs." + } + } + }, + "live": { + "label": "Live playback settings.", + "properties": { + "streams": { + "label": "Friendly names and restream names to use for live view." + }, + "height": { + "label": "Live camera view height" + }, + "quality": { + "label": "Live camera view quality" + } + } + }, + "lpr": { + "label": "LPR config.", + "properties": { + "enabled": { + "label": "Enable license plate recognition." + }, + "expire_time": { + "label": "Expire plates not seen after number of seconds (for dedicated LPR cameras only)." + }, + "min_area": { + "label": "Minimum area of license plate to begin running recognition." + }, + "enhancement": { + "label": "Amount of contrast adjustment and denoising to apply to license plate images before recognition." + } + } + }, + "motion": { + "label": "Motion detection configuration.", + "properties": { + "enabled": { + "label": "Enable motion on all cameras." + }, + "threshold": { + "label": "Motion detection threshold (1-255)." + }, + "lightning_threshold": { + "label": "Lightning detection threshold (0.3-1.0)." + }, + "improve_contrast": { + "label": "Improve Contrast" + }, + "contour_area": { + "label": "Contour Area" + }, + "delta_alpha": { + "label": "Delta Alpha" + }, + "frame_alpha": { + "label": "Frame Alpha" + }, + "frame_height": { + "label": "Frame Height" + }, + "mask": { + "label": "Coordinates polygon for the motion mask." + }, + "mqtt_off_delay": { + "label": "Delay for updating MQTT with no motion detected." + }, + "enabled_in_config": { + "label": "Keep track of original state of motion detection." + } + } + }, + "objects": { + "label": "Object configuration.", + "properties": { + "track": { + "label": "Objects to track." + }, + "filters": { + "label": "Object filters.", + "properties": { + "min_area": { + "label": "Minimum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "max_area": { + "label": "Maximum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "min_ratio": { + "label": "Minimum ratio of bounding box's width/height for object to be counted." + }, + "max_ratio": { + "label": "Maximum ratio of bounding box's width/height for object to be counted." + }, + "threshold": { + "label": "Average detection confidence threshold for object to be counted." + }, + "min_score": { + "label": "Minimum detection confidence for object to be counted." + }, + "mask": { + "label": "Detection area polygon mask for this filter configuration." + } + } + }, + "mask": { + "label": "Object mask." + }, + "genai": { + "label": "Config for using genai to analyze objects.", + "properties": { + "enabled": { + "label": "Enable GenAI for camera." + }, + "use_snapshot": { + "label": "Use snapshots for generating descriptions." + }, + "prompt": { + "label": "Default caption prompt." + }, + "object_prompts": { + "label": "Object specific prompts." + }, + "objects": { + "label": "List of objects to run generative AI for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to run generative AI." + }, + "debug_save_thumbnails": { + "label": "Save thumbnails sent to generative AI for debugging purposes." + }, + "send_triggers": { + "label": "What triggers to use to send frames to generative AI for a tracked object.", + "properties": { + "tracked_object_end": { + "label": "Send once the object is no longer tracked." + }, + "after_significant_updates": { + "label": "Send an early request to generative AI when X frames accumulated." + } + } + }, + "enabled_in_config": { + "label": "Keep track of original state of generative AI." + } + } + } + } + }, + "record": { + "label": "Record configuration.", + "properties": { + "enabled": { + "label": "Enable record on all cameras." + }, + "sync_recordings": { + "label": "Sync recordings with disk on startup and once a day." + }, + "expire_interval": { + "label": "Number of minutes to wait between cleanup runs." + }, + "continuous": { + "label": "Continuous recording retention settings.", + "properties": { + "days": { + "label": "Default retention period." + } + } + }, + "motion": { + "label": "Motion recording retention settings.", + "properties": { + "days": { + "label": "Default retention period." + } + } + }, + "detections": { + "label": "Detection specific retention settings.", + "properties": { + "pre_capture": { + "label": "Seconds to retain before event starts." + }, + "post_capture": { + "label": "Seconds to retain after event ends." + }, + "retain": { + "label": "Event retention settings.", + "properties": { + "days": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + } + } + } + } + }, + "alerts": { + "label": "Alert specific retention settings.", + "properties": { + "pre_capture": { + "label": "Seconds to retain before event starts." + }, + "post_capture": { + "label": "Seconds to retain after event ends." + }, + "retain": { + "label": "Event retention settings.", + "properties": { + "days": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + } + } + } + } + }, + "export": { + "label": "Recording Export Config", + "properties": { + "timelapse_args": { + "label": "Timelapse Args" + } + } + }, + "preview": { + "label": "Recording Preview Config", + "properties": { + "quality": { + "label": "Quality of recording preview." + } + } + }, + "enabled_in_config": { + "label": "Keep track of original state of recording." + } + } + }, + "review": { + "label": "Review configuration.", + "properties": { + "alerts": { + "label": "Review alerts config.", + "properties": { + "enabled": { + "label": "Enable alerts." + }, + "labels": { + "label": "Labels to create alerts for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save the event as an alert." + }, + "enabled_in_config": { + "label": "Keep track of original state of alerts." + }, + "cutoff_time": { + "label": "Time to cutoff alerts after no alert-causing activity has occurred." + } + } + }, + "detections": { + "label": "Review detections config.", + "properties": { + "enabled": { + "label": "Enable detections." + }, + "labels": { + "label": "Labels to create detections for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save the event as a detection." + }, + "cutoff_time": { + "label": "Time to cutoff detection after no detection-causing activity has occurred." + }, + "enabled_in_config": { + "label": "Keep track of original state of detections." + } + } + }, + "genai": { + "label": "Review description genai config.", + "properties": { + "enabled": { + "label": "Enable GenAI descriptions for review items." + }, + "alerts": { + "label": "Enable GenAI for alerts." + }, + "detections": { + "label": "Enable GenAI for detections." + }, + "additional_concerns": { + "label": "Additional concerns that GenAI should make note of on this camera." + }, + "debug_save_thumbnails": { + "label": "Save thumbnails sent to generative AI for debugging purposes." + }, + "enabled_in_config": { + "label": "Keep track of original state of generative AI." + }, + "preferred_language": { + "label": "Preferred language for GenAI Response" + }, + "activity_context_prompt": { + "label": "Custom activity context prompt defining normal activity patterns for this property." + } + } + } + } + }, + "semantic_search": { + "label": "Semantic search configuration.", + "properties": { + "triggers": { + "label": "Trigger actions on tracked objects that match existing thumbnails or descriptions", + "properties": { + "enabled": { + "label": "Enable this trigger" + }, + "type": { + "label": "Type of trigger" + }, + "data": { + "label": "Trigger content (text phrase or image ID)" + }, + "threshold": { + "label": "Confidence score required to run the trigger" + }, + "actions": { + "label": "Actions to perform when trigger is matched" + } + } + } + } + }, + "snapshots": { + "label": "Snapshot configuration.", + "properties": { + "enabled": { + "label": "Snapshots enabled." + }, + "clean_copy": { + "label": "Create a clean copy of the snapshot image." + }, + "timestamp": { + "label": "Add a timestamp overlay on the snapshot." + }, + "bounding_box": { + "label": "Add a bounding box overlay on the snapshot." + }, + "crop": { + "label": "Crop the snapshot to the detected object." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save a snapshot." + }, + "height": { + "label": "Snapshot image height." + }, + "retain": { + "label": "Snapshot retention.", + "properties": { + "default": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + }, + "objects": { + "label": "Object retention period." + } + } + }, + "quality": { + "label": "Quality of the encoded jpeg (0-100)." + } + } + }, + "timestamp_style": { + "label": "Timestamp style configuration.", + "properties": { + "position": { + "label": "Timestamp position." + }, + "format": { + "label": "Timestamp format." + }, + "color": { + "label": "Timestamp color.", + "properties": { + "red": { + "label": "Red" + }, + "green": { + "label": "Green" + }, + "blue": { + "label": "Blue" + } + } + }, + "thickness": { + "label": "Timestamp thickness." + }, + "effect": { + "label": "Timestamp effect." + } + } + }, + "best_image_timeout": { + "label": "How long to wait for the image with the highest confidence score." + }, + "mqtt": { + "label": "MQTT configuration.", + "properties": { + "enabled": { + "label": "Send image over MQTT." + }, + "timestamp": { + "label": "Add timestamp to MQTT image." + }, + "bounding_box": { + "label": "Add bounding box to MQTT image." + }, + "crop": { + "label": "Crop MQTT image to detected object." + }, + "height": { + "label": "MQTT image height." + }, + "required_zones": { + "label": "List of required zones to be entered in order to send the image." + }, + "quality": { + "label": "Quality of the encoded jpeg (0-100)." + } + } + }, + "notifications": { + "label": "Notifications configuration.", + "properties": { + "enabled": { + "label": "Enable notifications" + }, + "email": { + "label": "Email required for push." + }, + "cooldown": { + "label": "Cooldown period for notifications (time in seconds)." + }, + "enabled_in_config": { + "label": "Keep track of original state of notifications." + } + } + }, + "onvif": { + "label": "Camera Onvif Configuration.", + "properties": { + "host": { + "label": "Onvif Host" + }, + "port": { + "label": "Onvif Port" + }, + "user": { + "label": "Onvif Username" + }, + "password": { + "label": "Onvif Password" + }, + "tls_insecure": { + "label": "Onvif Disable TLS verification" + }, + "autotracking": { + "label": "PTZ auto tracking config.", + "properties": { + "enabled": { + "label": "Enable PTZ object autotracking." + }, + "calibrate_on_startup": { + "label": "Perform a camera calibration when Frigate starts." + }, + "zooming": { + "label": "Autotracker zooming mode." + }, + "zoom_factor": { + "label": "Zooming factor (0.1-0.75)." + }, + "track": { + "label": "Objects to track." + }, + "required_zones": { + "label": "List of required zones to be entered in order to begin autotracking." + }, + "return_preset": { + "label": "Name of camera preset to return to when object tracking is over." + }, + "timeout": { + "label": "Seconds to delay before returning to preset." + }, + "movement_weights": { + "label": "Internal value used for PTZ movements based on the speed of your camera's motor." + }, + "enabled_in_config": { + "label": "Keep track of original state of autotracking." + } + } + }, + "ignore_time_mismatch": { + "label": "Onvif Ignore Time Synchronization Mismatch Between Camera and Server" + } + } + }, + "type": { + "label": "Camera Type" + }, + "ui": { + "label": "Camera UI Modifications.", + "properties": { + "order": { + "label": "Order of camera in UI." + }, + "dashboard": { + "label": "Show this camera in Frigate dashboard UI." + } + } + }, + "webui_url": { + "label": "URL to visit the camera directly from system page" + }, + "zones": { + "label": "Zone configuration.", + "properties": { + "filters": { + "label": "Zone filters.", + "properties": { + "min_area": { + "label": "Minimum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "max_area": { + "label": "Maximum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "min_ratio": { + "label": "Minimum ratio of bounding box's width/height for object to be counted." + }, + "max_ratio": { + "label": "Maximum ratio of bounding box's width/height for object to be counted." + }, + "threshold": { + "label": "Average detection confidence threshold for object to be counted." + }, + "min_score": { + "label": "Minimum detection confidence for object to be counted." + }, + "mask": { + "label": "Detection area polygon mask for this filter configuration." + } + } + }, + "coordinates": { + "label": "Coordinates polygon for the defined zone." + }, + "distances": { + "label": "Real-world distances for the sides of quadrilateral for the defined zone." + }, + "inertia": { + "label": "Number of consecutive frames required for object to be considered present in the zone." + }, + "loitering_time": { + "label": "Number of seconds that an object must loiter to be considered in the zone." + }, + "speed_threshold": { + "label": "Minimum speed value for an object to be considered in the zone." + }, + "objects": { + "label": "List of objects that can trigger the zone." + } + } + }, + "enabled_in_config": { + "label": "Keep track of original state of camera." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/classification.json b/web/public/locales/en/config/classification.json new file mode 100644 index 000000000..e8014b2fa --- /dev/null +++ b/web/public/locales/en/config/classification.json @@ -0,0 +1,58 @@ +{ + "label": "Object classification config.", + "properties": { + "bird": { + "label": "Bird classification config.", + "properties": { + "enabled": { + "label": "Enable bird classification." + }, + "threshold": { + "label": "Minimum classification score required to be considered a match." + } + } + }, + "custom": { + "label": "Custom Classification Model Configs.", + "properties": { + "enabled": { + "label": "Enable running the model." + }, + "name": { + "label": "Name of classification model." + }, + "threshold": { + "label": "Classification score threshold to change the state." + }, + "object_config": { + "properties": { + "objects": { + "label": "Object types to classify." + }, + "classification_type": { + "label": "Type of classification that is applied." + } + } + }, + "state_config": { + "properties": { + "cameras": { + "label": "Cameras to run classification on.", + "properties": { + "crop": { + "label": "Crop of image frame on this camera to run classification on." + } + } + }, + "motion": { + "label": "If classification should be run when motion is detected in the crop." + }, + "interval": { + "label": "Interval to run classification on in seconds." + } + } + } + } + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/database.json b/web/public/locales/en/config/database.json new file mode 100644 index 000000000..ece7ccbaa --- /dev/null +++ b/web/public/locales/en/config/database.json @@ -0,0 +1,8 @@ +{ + "label": "Database configuration.", + "properties": { + "path": { + "label": "Database path." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/detect.json b/web/public/locales/en/config/detect.json new file mode 100644 index 000000000..9e1b59313 --- /dev/null +++ b/web/public/locales/en/config/detect.json @@ -0,0 +1,51 @@ +{ + "label": "Global object tracking configuration.", + "properties": { + "enabled": { + "label": "Detection Enabled." + }, + "height": { + "label": "Height of the stream for the detect role." + }, + "width": { + "label": "Width of the stream for the detect role." + }, + "fps": { + "label": "Number of frames per second to process through detection." + }, + "min_initialized": { + "label": "Minimum number of consecutive hits for an object to be initialized by the tracker." + }, + "max_disappeared": { + "label": "Maximum number of frames the object can disappear before detection ends." + }, + "stationary": { + "label": "Stationary objects config.", + "properties": { + "interval": { + "label": "Frame interval for checking stationary objects." + }, + "threshold": { + "label": "Number of frames without a position change for an object to be considered stationary" + }, + "max_frames": { + "label": "Max frames for stationary objects.", + "properties": { + "default": { + "label": "Default max frames." + }, + "objects": { + "label": "Object specific max frames." + } + } + }, + "classifier": { + "label": "Enable visual classifier for determing if objects with jittery bounding boxes are stationary." + } + } + }, + "annotation_offset": { + "label": "Milliseconds to offset detect annotations by." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/detectors.json b/web/public/locales/en/config/detectors.json new file mode 100644 index 000000000..1bd6fec70 --- /dev/null +++ b/web/public/locales/en/config/detectors.json @@ -0,0 +1,14 @@ +{ + "label": "Detector hardware configuration.", + "properties": { + "type": { + "label": "Detector Type" + }, + "model": { + "label": "Detector specific model configuration." + }, + "model_path": { + "label": "Detector specific model path." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/environment_vars.json b/web/public/locales/en/config/environment_vars.json new file mode 100644 index 000000000..ce97ce49e --- /dev/null +++ b/web/public/locales/en/config/environment_vars.json @@ -0,0 +1,3 @@ +{ + "label": "Frigate environment variables." +} \ No newline at end of file diff --git a/web/public/locales/en/config/face_recognition.json b/web/public/locales/en/config/face_recognition.json new file mode 100644 index 000000000..ec6f8929b --- /dev/null +++ b/web/public/locales/en/config/face_recognition.json @@ -0,0 +1,36 @@ +{ + "label": "Face recognition config.", + "properties": { + "enabled": { + "label": "Enable face recognition." + }, + "model_size": { + "label": "The size of the embeddings model used." + }, + "unknown_score": { + "label": "Minimum face distance score required to be marked as a potential match." + }, + "detection_threshold": { + "label": "Minimum face detection score required to be considered a face." + }, + "recognition_threshold": { + "label": "Minimum face distance score required to be considered a match." + }, + "min_area": { + "label": "Min area of face box to consider running face recognition." + }, + "min_faces": { + "label": "Min face recognitions for the sub label to be applied to the person object." + }, + "save_attempts": { + "label": "Number of face attempts to save in the train tab." + }, + "blur_confidence_filter": { + "label": "Apply blur quality filter to face confidence." + }, + "device": { + "label": "The device key to use for face recognition.", + "description": "This is an override, to target a specific device. See https://onnxruntime.ai/docs/execution-providers/ for more information" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/ffmpeg.json b/web/public/locales/en/config/ffmpeg.json new file mode 100644 index 000000000..570da5a35 --- /dev/null +++ b/web/public/locales/en/config/ffmpeg.json @@ -0,0 +1,34 @@ +{ + "label": "Global FFmpeg configuration.", + "properties": { + "path": { + "label": "FFmpeg path" + }, + "global_args": { + "label": "Global FFmpeg arguments." + }, + "hwaccel_args": { + "label": "FFmpeg hardware acceleration arguments." + }, + "input_args": { + "label": "FFmpeg input arguments." + }, + "output_args": { + "label": "FFmpeg output arguments per role.", + "properties": { + "detect": { + "label": "Detect role FFmpeg output arguments." + }, + "record": { + "label": "Record role FFmpeg output arguments." + } + } + }, + "retry_interval": { + "label": "Time in seconds to wait before FFmpeg retries connecting to the camera." + }, + "apple_compatibility": { + "label": "Set tag on HEVC (H.265) recording stream to improve compatibility with Apple players." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/genai.json b/web/public/locales/en/config/genai.json new file mode 100644 index 000000000..084b921c2 --- /dev/null +++ b/web/public/locales/en/config/genai.json @@ -0,0 +1,20 @@ +{ + "label": "Generative AI configuration.", + "properties": { + "api_key": { + "label": "Provider API key." + }, + "base_url": { + "label": "Provider base url." + }, + "model": { + "label": "GenAI model." + }, + "provider": { + "label": "GenAI provider." + }, + "provider_options": { + "label": "GenAI Provider extra options." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/go2rtc.json b/web/public/locales/en/config/go2rtc.json new file mode 100644 index 000000000..76ec33020 --- /dev/null +++ b/web/public/locales/en/config/go2rtc.json @@ -0,0 +1,3 @@ +{ + "label": "Global restream configuration." +} \ No newline at end of file diff --git a/web/public/locales/en/config/live.json b/web/public/locales/en/config/live.json new file mode 100644 index 000000000..362170137 --- /dev/null +++ b/web/public/locales/en/config/live.json @@ -0,0 +1,14 @@ +{ + "label": "Live playback settings.", + "properties": { + "streams": { + "label": "Friendly names and restream names to use for live view." + }, + "height": { + "label": "Live camera view height" + }, + "quality": { + "label": "Live camera view quality" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/logger.json b/web/public/locales/en/config/logger.json new file mode 100644 index 000000000..3d51786a7 --- /dev/null +++ b/web/public/locales/en/config/logger.json @@ -0,0 +1,11 @@ +{ + "label": "Logging configuration.", + "properties": { + "default": { + "label": "Default logging level." + }, + "logs": { + "label": "Log level for specified processes." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/lpr.json b/web/public/locales/en/config/lpr.json new file mode 100644 index 000000000..951d1f8f6 --- /dev/null +++ b/web/public/locales/en/config/lpr.json @@ -0,0 +1,45 @@ +{ + "label": "License Plate recognition config.", + "properties": { + "enabled": { + "label": "Enable license plate recognition." + }, + "model_size": { + "label": "The size of the embeddings model used." + }, + "detection_threshold": { + "label": "License plate object confidence score required to begin running recognition." + }, + "min_area": { + "label": "Minimum area of license plate to begin running recognition." + }, + "recognition_threshold": { + "label": "Recognition confidence score required to add the plate to the object as a sub label." + }, + "min_plate_length": { + "label": "Minimum number of characters a license plate must have to be added to the object as a sub label." + }, + "format": { + "label": "Regular expression for the expected format of license plate." + }, + "match_distance": { + "label": "Allow this number of missing/incorrect characters to still cause a detected plate to match a known plate." + }, + "known_plates": { + "label": "Known plates to track (strings or regular expressions)." + }, + "enhancement": { + "label": "Amount of contrast adjustment and denoising to apply to license plate images before recognition." + }, + "debug_save_plates": { + "label": "Save plates captured for LPR for debugging purposes." + }, + "device": { + "label": "The device key to use for LPR.", + "description": "This is an override, to target a specific device. See https://onnxruntime.ai/docs/execution-providers/ for more information" + }, + "replace_rules": { + "label": "List of regex replacement rules for normalizing detected plates. Each rule has 'pattern' and 'replacement'." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/model.json b/web/public/locales/en/config/model.json new file mode 100644 index 000000000..0bc2c1ddf --- /dev/null +++ b/web/public/locales/en/config/model.json @@ -0,0 +1,35 @@ +{ + "label": "Detection model configuration.", + "properties": { + "path": { + "label": "Custom Object detection model path." + }, + "labelmap_path": { + "label": "Label map for custom object detector." + }, + "width": { + "label": "Object detection model input width." + }, + "height": { + "label": "Object detection model input height." + }, + "labelmap": { + "label": "Labelmap customization." + }, + "attributes_map": { + "label": "Map of object labels to their attribute labels." + }, + "input_tensor": { + "label": "Model Input Tensor Shape" + }, + "input_pixel_format": { + "label": "Model Input Pixel Color Format" + }, + "input_dtype": { + "label": "Model Input D Type" + }, + "model_type": { + "label": "Object Detection Model Type" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/motion.json b/web/public/locales/en/config/motion.json new file mode 100644 index 000000000..183bfdf34 --- /dev/null +++ b/web/public/locales/en/config/motion.json @@ -0,0 +1,3 @@ +{ + "label": "Global motion detection configuration." +} \ No newline at end of file diff --git a/web/public/locales/en/config/mqtt.json b/web/public/locales/en/config/mqtt.json new file mode 100644 index 000000000..d2625ac83 --- /dev/null +++ b/web/public/locales/en/config/mqtt.json @@ -0,0 +1,44 @@ +{ + "label": "MQTT configuration.", + "properties": { + "enabled": { + "label": "Enable MQTT Communication." + }, + "host": { + "label": "MQTT Host" + }, + "port": { + "label": "MQTT Port" + }, + "topic_prefix": { + "label": "MQTT Topic Prefix" + }, + "client_id": { + "label": "MQTT Client ID" + }, + "stats_interval": { + "label": "MQTT Camera Stats Interval" + }, + "user": { + "label": "MQTT Username" + }, + "password": { + "label": "MQTT Password" + }, + "tls_ca_certs": { + "label": "MQTT TLS CA Certificates" + }, + "tls_client_cert": { + "label": "MQTT TLS Client Certificate" + }, + "tls_client_key": { + "label": "MQTT TLS Client Key" + }, + "tls_insecure": { + "label": "MQTT TLS Insecure" + }, + "qos": { + "label": "MQTT QoS" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/networking.json b/web/public/locales/en/config/networking.json new file mode 100644 index 000000000..0f8d9cc54 --- /dev/null +++ b/web/public/locales/en/config/networking.json @@ -0,0 +1,13 @@ +{ + "label": "Networking configuration", + "properties": { + "ipv6": { + "label": "Network configuration", + "properties": { + "enabled": { + "label": "Enable IPv6 for port 5000 and/or 8971" + } + } + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/notifications.json b/web/public/locales/en/config/notifications.json new file mode 100644 index 000000000..b529f10e0 --- /dev/null +++ b/web/public/locales/en/config/notifications.json @@ -0,0 +1,17 @@ +{ + "label": "Global notification configuration.", + "properties": { + "enabled": { + "label": "Enable notifications" + }, + "email": { + "label": "Email required for push." + }, + "cooldown": { + "label": "Cooldown period for notifications (time in seconds)." + }, + "enabled_in_config": { + "label": "Keep track of original state of notifications." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/objects.json b/web/public/locales/en/config/objects.json new file mode 100644 index 000000000..f041672a0 --- /dev/null +++ b/web/public/locales/en/config/objects.json @@ -0,0 +1,77 @@ +{ + "label": "Global object configuration.", + "properties": { + "track": { + "label": "Objects to track." + }, + "filters": { + "label": "Object filters.", + "properties": { + "min_area": { + "label": "Minimum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "max_area": { + "label": "Maximum area of bounding box for object to be counted. Can be pixels (int) or percentage (float between 0.000001 and 0.99)." + }, + "min_ratio": { + "label": "Minimum ratio of bounding box's width/height for object to be counted." + }, + "max_ratio": { + "label": "Maximum ratio of bounding box's width/height for object to be counted." + }, + "threshold": { + "label": "Average detection confidence threshold for object to be counted." + }, + "min_score": { + "label": "Minimum detection confidence for object to be counted." + }, + "mask": { + "label": "Detection area polygon mask for this filter configuration." + } + } + }, + "mask": { + "label": "Object mask." + }, + "genai": { + "label": "Config for using genai to analyze objects.", + "properties": { + "enabled": { + "label": "Enable GenAI for camera." + }, + "use_snapshot": { + "label": "Use snapshots for generating descriptions." + }, + "prompt": { + "label": "Default caption prompt." + }, + "object_prompts": { + "label": "Object specific prompts." + }, + "objects": { + "label": "List of objects to run generative AI for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to run generative AI." + }, + "debug_save_thumbnails": { + "label": "Save thumbnails sent to generative AI for debugging purposes." + }, + "send_triggers": { + "label": "What triggers to use to send frames to generative AI for a tracked object.", + "properties": { + "tracked_object_end": { + "label": "Send once the object is no longer tracked." + }, + "after_significant_updates": { + "label": "Send an early request to generative AI when X frames accumulated." + } + } + }, + "enabled_in_config": { + "label": "Keep track of original state of generative AI." + } + } + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/proxy.json b/web/public/locales/en/config/proxy.json new file mode 100644 index 000000000..732d6fafd --- /dev/null +++ b/web/public/locales/en/config/proxy.json @@ -0,0 +1,31 @@ +{ + "label": "Proxy configuration.", + "properties": { + "header_map": { + "label": "Header mapping definitions for proxy user passing.", + "properties": { + "user": { + "label": "Header name from upstream proxy to identify user." + }, + "role": { + "label": "Header name from upstream proxy to identify user role." + }, + "role_map": { + "label": "Mapping of Frigate roles to upstream group values. " + } + } + }, + "logout_url": { + "label": "Redirect url for logging out with proxy." + }, + "auth_secret": { + "label": "Secret value for proxy authentication." + }, + "default_role": { + "label": "Default role for proxy users." + }, + "separator": { + "label": "The character used to separate values in a mapped header." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/record.json b/web/public/locales/en/config/record.json new file mode 100644 index 000000000..81139084e --- /dev/null +++ b/web/public/locales/en/config/record.json @@ -0,0 +1,93 @@ +{ + "label": "Global record configuration.", + "properties": { + "enabled": { + "label": "Enable record on all cameras." + }, + "sync_recordings": { + "label": "Sync recordings with disk on startup and once a day." + }, + "expire_interval": { + "label": "Number of minutes to wait between cleanup runs." + }, + "continuous": { + "label": "Continuous recording retention settings.", + "properties": { + "days": { + "label": "Default retention period." + } + } + }, + "motion": { + "label": "Motion recording retention settings.", + "properties": { + "days": { + "label": "Default retention period." + } + } + }, + "detections": { + "label": "Detection specific retention settings.", + "properties": { + "pre_capture": { + "label": "Seconds to retain before event starts." + }, + "post_capture": { + "label": "Seconds to retain after event ends." + }, + "retain": { + "label": "Event retention settings.", + "properties": { + "days": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + } + } + } + } + }, + "alerts": { + "label": "Alert specific retention settings.", + "properties": { + "pre_capture": { + "label": "Seconds to retain before event starts." + }, + "post_capture": { + "label": "Seconds to retain after event ends." + }, + "retain": { + "label": "Event retention settings.", + "properties": { + "days": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + } + } + } + } + }, + "export": { + "label": "Recording Export Config", + "properties": { + "timelapse_args": { + "label": "Timelapse Args" + } + } + }, + "preview": { + "label": "Recording Preview Config", + "properties": { + "quality": { + "label": "Quality of recording preview." + } + } + }, + "enabled_in_config": { + "label": "Keep track of original state of recording." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/review.json b/web/public/locales/en/config/review.json new file mode 100644 index 000000000..a44c2cfa9 --- /dev/null +++ b/web/public/locales/en/config/review.json @@ -0,0 +1,74 @@ +{ + "label": "Review configuration.", + "properties": { + "alerts": { + "label": "Review alerts config.", + "properties": { + "enabled": { + "label": "Enable alerts." + }, + "labels": { + "label": "Labels to create alerts for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save the event as an alert." + }, + "enabled_in_config": { + "label": "Keep track of original state of alerts." + }, + "cutoff_time": { + "label": "Time to cutoff alerts after no alert-causing activity has occurred." + } + } + }, + "detections": { + "label": "Review detections config.", + "properties": { + "enabled": { + "label": "Enable detections." + }, + "labels": { + "label": "Labels to create detections for." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save the event as a detection." + }, + "cutoff_time": { + "label": "Time to cutoff detection after no detection-causing activity has occurred." + }, + "enabled_in_config": { + "label": "Keep track of original state of detections." + } + } + }, + "genai": { + "label": "Review description genai config.", + "properties": { + "enabled": { + "label": "Enable GenAI descriptions for review items." + }, + "alerts": { + "label": "Enable GenAI for alerts." + }, + "detections": { + "label": "Enable GenAI for detections." + }, + "additional_concerns": { + "label": "Additional concerns that GenAI should make note of on this camera." + }, + "debug_save_thumbnails": { + "label": "Save thumbnails sent to generative AI for debugging purposes." + }, + "enabled_in_config": { + "label": "Keep track of original state of generative AI." + }, + "preferred_language": { + "label": "Preferred language for GenAI Response" + }, + "activity_context_prompt": { + "label": "Custom activity context prompt defining normal activity patterns for this property." + } + } + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/safe_mode.json b/web/public/locales/en/config/safe_mode.json new file mode 100644 index 000000000..352f78b29 --- /dev/null +++ b/web/public/locales/en/config/safe_mode.json @@ -0,0 +1,3 @@ +{ + "label": "If Frigate should be started in safe mode." +} \ No newline at end of file diff --git a/web/public/locales/en/config/semantic_search.json b/web/public/locales/en/config/semantic_search.json new file mode 100644 index 000000000..2c46640bb --- /dev/null +++ b/web/public/locales/en/config/semantic_search.json @@ -0,0 +1,21 @@ +{ + "label": "Semantic search configuration.", + "properties": { + "enabled": { + "label": "Enable semantic search." + }, + "reindex": { + "label": "Reindex all tracked objects on startup." + }, + "model": { + "label": "The CLIP model to use for semantic search." + }, + "model_size": { + "label": "The size of the embeddings model used." + }, + "device": { + "label": "The device key to use for semantic search.", + "description": "This is an override, to target a specific device. See https://onnxruntime.ai/docs/execution-providers/ for more information" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/snapshots.json b/web/public/locales/en/config/snapshots.json new file mode 100644 index 000000000..a6336140e --- /dev/null +++ b/web/public/locales/en/config/snapshots.json @@ -0,0 +1,43 @@ +{ + "label": "Global snapshots configuration.", + "properties": { + "enabled": { + "label": "Snapshots enabled." + }, + "clean_copy": { + "label": "Create a clean copy of the snapshot image." + }, + "timestamp": { + "label": "Add a timestamp overlay on the snapshot." + }, + "bounding_box": { + "label": "Add a bounding box overlay on the snapshot." + }, + "crop": { + "label": "Crop the snapshot to the detected object." + }, + "required_zones": { + "label": "List of required zones to be entered in order to save a snapshot." + }, + "height": { + "label": "Snapshot image height." + }, + "retain": { + "label": "Snapshot retention.", + "properties": { + "default": { + "label": "Default retention period." + }, + "mode": { + "label": "Retain mode." + }, + "objects": { + "label": "Object retention period." + } + } + }, + "quality": { + "label": "Quality of the encoded jpeg (0-100)." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/telemetry.json b/web/public/locales/en/config/telemetry.json new file mode 100644 index 000000000..802ced2a0 --- /dev/null +++ b/web/public/locales/en/config/telemetry.json @@ -0,0 +1,28 @@ +{ + "label": "Telemetry configuration.", + "properties": { + "network_interfaces": { + "label": "Enabled network interfaces for bandwidth calculation." + }, + "stats": { + "label": "System Stats Configuration", + "properties": { + "amd_gpu_stats": { + "label": "Enable AMD GPU stats." + }, + "intel_gpu_stats": { + "label": "Enable Intel GPU stats." + }, + "network_bandwidth": { + "label": "Enable network bandwidth for ffmpeg processes." + }, + "intel_gpu_device": { + "label": "Define the device to use when gathering SR-IOV stats." + } + } + }, + "version_check": { + "label": "Enable latest version check." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/timestamp_style.json b/web/public/locales/en/config/timestamp_style.json new file mode 100644 index 000000000..6a3119423 --- /dev/null +++ b/web/public/locales/en/config/timestamp_style.json @@ -0,0 +1,31 @@ +{ + "label": "Global timestamp style configuration.", + "properties": { + "position": { + "label": "Timestamp position." + }, + "format": { + "label": "Timestamp format." + }, + "color": { + "label": "Timestamp color.", + "properties": { + "red": { + "label": "Red" + }, + "green": { + "label": "Green" + }, + "blue": { + "label": "Blue" + } + } + }, + "thickness": { + "label": "Timestamp thickness." + }, + "effect": { + "label": "Timestamp effect." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/tls.json b/web/public/locales/en/config/tls.json new file mode 100644 index 000000000..58493ff40 --- /dev/null +++ b/web/public/locales/en/config/tls.json @@ -0,0 +1,8 @@ +{ + "label": "TLS configuration.", + "properties": { + "enabled": { + "label": "Enable TLS for port 8971" + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/ui.json b/web/public/locales/en/config/ui.json new file mode 100644 index 000000000..fec0a9528 --- /dev/null +++ b/web/public/locales/en/config/ui.json @@ -0,0 +1,23 @@ +{ + "label": "UI configuration.", + "properties": { + "timezone": { + "label": "Override UI timezone." + }, + "time_format": { + "label": "Override UI time format." + }, + "date_style": { + "label": "Override UI dateStyle." + }, + "time_style": { + "label": "Override UI timeStyle." + }, + "strftime_fmt": { + "label": "Override date and time format using strftime syntax." + }, + "unit_system": { + "label": "The unit system to use for measurements." + } + } +} \ No newline at end of file diff --git a/web/public/locales/en/config/version.json b/web/public/locales/en/config/version.json new file mode 100644 index 000000000..e777d7573 --- /dev/null +++ b/web/public/locales/en/config/version.json @@ -0,0 +1,3 @@ +{ + "label": "Current config version." +} \ No newline at end of file