frigate/web/public/locales/en/common.json
Josh Hawkins c93dad9bd9
Camera profile support (#22482)
* add CameraProfileConfig model for named config overrides

* add profiles field to CameraConfig

* add active_profile field to FrigateConfig

Runtime-only field excluded from YAML serialization, tracks which
profile is currently active.

* add ProfileManager for profile activation and persistence

Handles snapshotting base configs, applying profile overrides via
deep_merge + apply_section_update, publishing ZMQ updates, and
persisting active profile to /config/.active_profile.

* add profile API endpoints (GET /profiles, GET/PUT /profile)

* add MQTT and dispatcher integration for profiles

- Subscribe to frigate/profile/set MQTT topic
- Publish profile/state and profiles/available on connect
- Add _on_profile_command handler to dispatcher
- Broadcast active profile state on WebSocket connect

* wire ProfileManager into app startup and FastAPI

- Create ProfileManager after dispatcher init
- Restore persisted profile on startup
- Pass dispatcher and profile_manager to FastAPI app

* add tests for invalid profile values and keys

Tests that Pydantic rejects: invalid field values (fps: "not_a_number"),
unknown section keys (ffmpeg in profile), invalid nested values, and
invalid profiles in full config parsing.

* formatting

* fix CameraLiveConfig JSON serialization error on profile activation

refactor _publish_updates to only publish ZMQ updates for
sections that actually changed, not all sections on affected cameras.

* consolidate

* add enabled field to camera profiles for enabling/disabling cameras

* add zones support to camera profiles

* add frontend profile types, color utility, and config save support

* add profile state management and save preview support

* add profileName prop to BaseSection for profile-aware config editing

* add profile section dropdown and wire into camera settings pages

* add per-profile camera enable/disable to Camera Management view

* add profiles summary page with card-based layout and fix backend zone comparison bug

* add active profile badge to settings toolbar

* i18n

* add red dot for any pending changes including profiles

* profile support for mask and zone editor

* fix hidden field validation errors caused by lodash wildcard and schema gaps

lodash unset does not support wildcard (*) segments, so hidden fields like
filters.*.mask were never stripped from form data, leaving null raw_coordinates
that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip
hidden fields from the JSON schema itself as defense-in-depth.

* add face_recognition and lpr to profile-eligible sections

* move profile dropdown from section panes to settings header

* add profiles enable toggle and improve empty state

* formatting

* tweaks

* tweak colors and switch

* fix profile save diff, masksAndZones delete, and config sync

* ui tweaks

* ensure profile manager gets updated config

* rename profile settings to ui settings

* refactor profilesview and add dots/border colors when overridden

* implement an update_config method for profile manager

* fix mask deletion

* more unique colors

* add top-level profiles config section with friendly names

* implement profile friendly names and improve profile UI

- Add ProfileDefinitionConfig type and profiles field to FrigateConfig
- Use ProfilesApiResponse type with friendly_name support throughout
- Replace Record<string, unknown> with proper JsonObject/JsonValue types
- Add profile creation form matching zone pattern (Zod + NameAndIdFields)
- Add pencil icon for renaming profile friendly names in ProfilesView
- Move Profiles menu item to first under Camera Configuration
- Add activity indicators on save/rename/delete buttons
- Display friendly names in CameraManagementView profile selector
- Fix duplicate colored dots in management profile dropdown
- Fix i18n namespace for overridden base config tooltips
- Move profile override deletion from dropdown trash icon to footer
  button with confirmation dialog, matching Reset to Global pattern
- Remove Add Profile from section header dropdown to prevent saving
  camera overrides before top-level profile definition exists
- Clean up newProfiles state after API profile deletion
- Refresh profiles SWR cache after saving profile definitions

* remove profile badge in settings and add profiles to main menu

* use icon only on mobile

* change color order

* docs

* show activity indicator on trash icon while deleting a profile

* tweak language

* immediately create profiles on backend instead of deferring to Save All

* hide restart-required fields when editing a profile section

fields that require a restart cannot take effect via profile switching,
so they are merged into hiddenFields when profileName is set

* show active profile indicator in desktop status bar

* fix profile config inheritance bug where Pydantic defaults override base values

The /config API was dumping profile overrides with model_dump() which included
all Pydantic defaults. When the frontend merged these over
the camera's base config, explicitly-set base values were
lost. Now profile overrides are re-dumped with exclude_unset=True so only
user-specified fields are returned.

Also fixes the Save All path generating spurious deletion markers for
restart-required fields that are hidden during profile
editing but not excluded from the raw data sanitization in
prepareSectionSavePayload.

* docs tweaks

* docs tweak

* formatting

* formatting

* fix typing

* fix test pollution

test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed

* remove

* fix settings showing profile-merged values when editing base config

When a profile is active, the in-memory config contains effective
(profile-merged) values. The settings UI was displaying these merged
values even when the "Base Config" view was selected.

Backend: snapshot pre-profile base configs in ProfileManager and expose
them via a `base_config` key in the /api/config camera response when a
profile is active. The top-level sections continue to reflect the
effective running config.

Frontend: read from `base_config` when available in BaseSection,
useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload.
Include formData labels in Object/Audio switches widgets so that labels
added only by a profile override remain visible when editing that profile.

* use rasterized_mask as field

makes it easier to exclude from the schema with exclude=True
prevents leaking of the field when using model_dump for profiles

* fix zones

- Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field
- Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view
- Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation)
- Inherit base zone color and generate contours for profile zone overrides in profile manager

* formatting

* don't require restart for camera enabled change for profiles

* publish camera state when changing profiles

* formatting

* remove available profiles from mqtt

* improve typing
2026-03-19 09:47:57 -05:00

315 lines
8.5 KiB
JSON

{
"time": {
"untilForTime": "Until {{time}}",
"untilForRestart": "Until Frigate restarts.",
"untilRestart": "Until restart",
"never": "Never",
"ago": "{{timeAgo}} ago",
"justNow": "Just now",
"today": "Today",
"yesterday": "Yesterday",
"last7": "Last 7 days",
"last14": "Last 14 days",
"last30": "Last 30 days",
"thisWeek": "This Week",
"lastWeek": "Last Week",
"thisMonth": "This Month",
"lastMonth": "Last Month",
"5minutes": "5 minutes",
"10minutes": "10 minutes",
"30minutes": "30 minutes",
"1hour": "1 hour",
"12hours": "12 hours",
"24hours": "24 hours",
"pm": "pm",
"am": "am",
"yr": "{{time}}yr",
"year_one": "{{time}} year",
"year_other": "{{time}} years",
"mo": "{{time}}mo",
"month_one": "{{time}} month",
"month_other": "{{time}} months",
"d": "{{time}}d",
"day_one": "{{time}} day",
"day_other": "{{time}} days",
"h": "{{time}}h",
"hour_one": "{{time}} hour",
"hour_other": "{{time}} hours",
"m": "{{time}}m",
"minute_one": "{{time}} minute",
"minute_other": "{{time}} minutes",
"s": "{{time}}s",
"second_one": "{{time}} second",
"second_other": "{{time}} seconds",
"formattedTimestamp": {
"12hour": "MMM d, h:mm:ss aaa",
"24hour": "MMM d, HH:mm:ss"
},
"formattedTimestamp2": {
"12hour": "MM/dd h:mm:ssa",
"24hour": "d MMM HH:mm:ss"
},
"formattedTimestampHourMinute": {
"12hour": "h:mm aaa",
"24hour": "HH:mm"
},
"formattedTimestampHourMinuteSecond": {
"12hour": "h:mm:ss aaa",
"24hour": "HH:mm:ss"
},
"formattedTimestampMonthDayHourMinute": {
"12hour": "MMM d, h:mm aaa",
"24hour": "MMM d, HH:mm"
},
"formattedTimestampMonthDayYear": {
"12hour": "MMM d, yyyy",
"24hour": "MMM d, yyyy"
},
"formattedTimestampMonthDayYearHourMinute": {
"12hour": "MMM d yyyy, h:mm aaa",
"24hour": "MMM d yyyy, HH:mm"
},
"formattedTimestampMonthDay": "MMM d",
"formattedTimestampFilename": {
"12hour": "MM-dd-yy-h-mm-ss-a",
"24hour": "MM-dd-yy-HH-mm-ss"
},
"inProgress": "In progress",
"invalidStartTime": "Invalid start time",
"invalidEndTime": "Invalid end time"
},
"unit": {
"speed": {
"mph": "mph",
"kph": "kph"
},
"length": {
"feet": "feet",
"meters": "meters"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/hour",
"mbph": "MB/hour",
"gbph": "GB/hour"
}
},
"label": {
"back": "Go back",
"hide": "Hide {{item}}",
"show": "Show {{item}}",
"ID": "ID",
"none": "None",
"all": "All",
"other": "Other"
},
"list": {
"two": "{{0}} and {{1}}",
"many": "{{items}}, and {{last}}",
"separatorWithSpace": ", "
},
"field": {
"optional": "Optional",
"internalID": "The Internal ID Frigate uses in the configuration and database"
},
"button": {
"add": "Add",
"apply": "Apply",
"applying": "Applying…",
"reset": "Reset",
"undo": "Undo",
"done": "Done",
"enabled": "Enabled",
"enable": "Enable",
"disabled": "Disabled",
"disable": "Disable",
"save": "Save",
"saving": "Saving…",
"cancel": "Cancel",
"close": "Close",
"copy": "Copy",
"copiedToClipboard": "Copied to clipboard",
"back": "Back",
"history": "History",
"fullscreen": "Fullscreen",
"exitFullscreen": "Exit Fullscreen",
"pictureInPicture": "Picture in Picture",
"twoWayTalk": "Two Way Talk",
"cameraAudio": "Camera Audio",
"on": "ON",
"off": "OFF",
"edit": "Edit",
"copyCoordinates": "Copy coordinates",
"delete": "Delete",
"yes": "Yes",
"no": "No",
"download": "Download",
"info": "Info",
"suspended": "Suspended",
"unsuspended": "Unsuspend",
"play": "Play",
"unselect": "Unselect",
"export": "Export",
"deleteNow": "Delete Now",
"next": "Next",
"continue": "Continue",
"modified": "Modified",
"overridden": "Overridden",
"resetToGlobal": "Reset to Global",
"resetToDefault": "Reset to Default",
"saveAll": "Save All",
"savingAll": "Saving All…",
"undoAll": "Undo All"
},
"menu": {
"system": "System",
"systemMetrics": "System metrics",
"configuration": "Configuration",
"systemLogs": "System logs",
"profiles": "Profiles",
"settings": "Settings",
"configurationEditor": "Configuration Editor",
"languages": "Languages",
"language": {
"en": "English (English)",
"es": "Español (Spanish)",
"zhCN": "简体中文 (Simplified Chinese)",
"hi": "हिन्दी (Hindi)",
"fr": "Français (French)",
"ar": "العربية (Arabic)",
"pt": "Português (Portuguese)",
"ptBR": "Português brasileiro (Brazilian Portuguese)",
"ru": "Русский (Russian)",
"de": "Deutsch (German)",
"ja": "日本語 (Japanese)",
"tr": "Türkçe (Turkish)",
"it": "Italiano (Italian)",
"nl": "Nederlands (Dutch)",
"sv": "Svenska (Swedish)",
"cs": "Čeština (Czech)",
"nb": "Norsk Bokmål (Norwegian Bokmål)",
"ko": "한국어 (Korean)",
"vi": "Tiếng Việt (Vietnamese)",
"fa": "فارسی (Persian)",
"pl": "Polski (Polish)",
"uk": "Українська (Ukrainian)",
"he": "עברית (Hebrew)",
"el": "Ελληνικά (Greek)",
"ro": "Română (Romanian)",
"hu": "Magyar (Hungarian)",
"fi": "Suomi (Finnish)",
"da": "Dansk (Danish)",
"sk": "Slovenčina (Slovak)",
"yue": "粵語 (Cantonese)",
"th": "ไทย (Thai)",
"ca": "Català (Catalan)",
"hr": "Hrvatski (Croatian)",
"sr": "Српски (Serbian)",
"sl": "Slovenščina (Slovenian)",
"lt": "Lietuvių (Lithuanian)",
"bg": "Български (Bulgarian)",
"gl": "Galego (Galician)",
"id": "Bahasa Indonesia (Indonesian)",
"ur": "اردو (Urdu)",
"withSystem": {
"label": "Use the system settings for language"
}
},
"appearance": "Appearance",
"darkMode": {
"label": "Dark Mode",
"light": "Light",
"dark": "Dark",
"withSystem": {
"label": "Use the system settings for light or dark mode"
}
},
"withSystem": "System",
"theme": {
"label": "Theme",
"blue": "Blue",
"green": "Green",
"nord": "Nord",
"red": "Red",
"highcontrast": "High Contrast",
"default": "Default"
},
"help": "Help",
"documentation": {
"title": "Documentation",
"label": "Frigate documentation"
},
"restart": "Restart Frigate",
"live": {
"title": "Live",
"allCameras": "All Cameras",
"cameras": {
"title": "Cameras",
"count_one": "{{count}} Camera",
"count_other": "{{count}} Cameras"
}
},
"review": "Review",
"explore": "Explore",
"export": "Export",
"actions": "Actions",
"uiPlayground": "UI Playground",
"faceLibrary": "Face Library",
"classification": "Classification",
"chat": "Chat",
"user": {
"title": "User",
"account": "Account",
"current": "Current User: {{user}}",
"anonymous": "anonymous",
"logout": "Logout",
"setPassword": "Set Password"
}
},
"toast": {
"copyUrlToClipboard": "Copied URL to clipboard.",
"save": {
"title": "Save",
"error": {
"title": "Failed to save config changes: {{errorMessage}}",
"noMessage": "Failed to save config changes"
}
}
},
"role": {
"title": "Role",
"admin": "Admin",
"viewer": "Viewer",
"desc": "Admins have full access to all features in the Frigate UI. Viewers are limited to viewing cameras, review items, and historical footage in the UI."
},
"pagination": {
"label": "pagination",
"previous": {
"title": "Previous",
"label": "Go to previous page"
},
"next": {
"title": "Next",
"label": "Go to next page"
},
"more": "More pages"
},
"accessDenied": {
"documentTitle": "Access Denied - Frigate",
"title": "Access Denied",
"desc": "You don't have permission to view this page."
},
"notFound": {
"documentTitle": "Not Found - Frigate",
"title": "404",
"desc": "Page not found"
},
"selectItem": "Select {{item}}",
"readTheDocumentation": "Read the documentation",
"information": {
"pixels": "{{area}}px"
}
}