From aad24497bfb903d60df5edc6ebc3fb7ef9fcab76 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 29 Jan 2026 08:40:29 -0600 Subject: [PATCH] add config groups as a separate i18n namespace --- web/public/locales/en/config/audio.json | 4 --- web/public/locales/en/config/detect.json | 4 --- web/public/locales/en/config/groups.json | 28 +++++++++++++++++++ web/public/locales/en/config/motion.json | 4 --- web/public/locales/en/config/objects.json | 4 --- web/public/locales/en/config/record.json | 4 --- web/public/locales/en/config/snapshots.json | 3 -- .../locales/en/config/timestamp_style.json | 3 -- .../theme/templates/ObjectFieldTemplate.tsx | 24 +++++++++++++--- web/src/utils/i18n.ts | 1 + 10 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 web/public/locales/en/config/groups.json diff --git a/web/public/locales/en/config/audio.json b/web/public/locales/en/config/audio.json index 4532a91c0..71fbc1530 100644 --- a/web/public/locales/en/config/audio.json +++ b/web/public/locales/en/config/audio.json @@ -1,10 +1,6 @@ { "label": "Audio events", "description": "settings for audio-based event detection; camera-level settings can override these.", - "groups": { - "detection": "Detection", - "sensitivity": "Sensitivity" - }, "enabled": { "label": "Enable audio events", "description": "Enable or disable audio event detection globally. Can be overridden per camera." diff --git a/web/public/locales/en/config/detect.json b/web/public/locales/en/config/detect.json index 889ea1456..7cc2d43ac 100644 --- a/web/public/locales/en/config/detect.json +++ b/web/public/locales/en/config/detect.json @@ -1,10 +1,6 @@ { "label": "Object Detection", "description": "Settings for the detection/detect role used to run object detection and initialize trackers.", - "groups": { - "resolution": "Resolution", - "tracking": "Tracking" - }, "enabled": { "label": "Detection Enabled", "description": "Enable or disable object detection for this camera. Detection must be enabled for object tracking to run." diff --git a/web/public/locales/en/config/groups.json b/web/public/locales/en/config/groups.json new file mode 100644 index 000000000..abff0d24d --- /dev/null +++ b/web/public/locales/en/config/groups.json @@ -0,0 +1,28 @@ +{ + "audio": { + "detection": "Detection", + "sensitivity": "Sensitivity" + }, + "timestamp_style": { + "appearance": "Appearance" + }, + "motion": { + "sensitivity": "Sensitivity", + "algorithm": "Algorithm" + }, + "snapshots": { + "display": "Display" + }, + "detect": { + "resolution": "Resolution", + "tracking": "Tracking" + }, + "objects": { + "tracking": "Tracking", + "filtering": "Filtering" + }, + "record": { + "retention": "Retention", + "events": "Events" + } +} diff --git a/web/public/locales/en/config/motion.json b/web/public/locales/en/config/motion.json index e95d75199..cb2b08bab 100644 --- a/web/public/locales/en/config/motion.json +++ b/web/public/locales/en/config/motion.json @@ -1,10 +1,6 @@ { "label": "Motion detection", "description": "Default motion detection settings applied to cameras unless overridden per-camera.", - "groups": { - "sensitivity": "Sensitivity", - "algorithm": "Algorithm" - }, "enabled": { "label": "Enable motion detection", "description": "Enable or disable motion detection globally; per-camera settings can override this." diff --git a/web/public/locales/en/config/objects.json b/web/public/locales/en/config/objects.json index f524b97b6..c7acbd3f1 100644 --- a/web/public/locales/en/config/objects.json +++ b/web/public/locales/en/config/objects.json @@ -1,10 +1,6 @@ { "label": "Objects", "description": "Object tracking defaults including which labels to track and per-object filters.", - "groups": { - "tracking": "Tracking", - "filtering": "Filtering" - }, "track": { "label": "Objects to track", "description": "List of object labels to track globally; camera configs can override this." diff --git a/web/public/locales/en/config/record.json b/web/public/locales/en/config/record.json index 1e198376f..d4a58a567 100644 --- a/web/public/locales/en/config/record.json +++ b/web/public/locales/en/config/record.json @@ -1,10 +1,6 @@ { "label": "Recording", "description": "Recording and retention settings applied to cameras unless overridden per-camera.", - "groups": { - "retention": "Retention", - "events": "Events" - }, "enabled": { "label": "Enable record on all cameras", "description": "Enable or disable recording globally; individual cameras can override this." diff --git a/web/public/locales/en/config/snapshots.json b/web/public/locales/en/config/snapshots.json index d9ee28a46..23087fb4b 100644 --- a/web/public/locales/en/config/snapshots.json +++ b/web/public/locales/en/config/snapshots.json @@ -1,9 +1,6 @@ { "label": "Snapshots", "description": "Settings for saved JPEG snapshots of tracked objects; can be overridden per-camera.", - "groups": { - "display": "Display" - }, "enabled": { "label": "Snapshots enabled", "description": "Enable or disable saving snapshots globally." diff --git a/web/public/locales/en/config/timestamp_style.json b/web/public/locales/en/config/timestamp_style.json index 2a509fddc..60b5af16f 100644 --- a/web/public/locales/en/config/timestamp_style.json +++ b/web/public/locales/en/config/timestamp_style.json @@ -1,9 +1,6 @@ { "label": "Timestamp style", "description": "Styling options for in-feed timestamps applied to recordings and snapshots.", - "groups": { - "appearance": "Appearance" - }, "position": { "label": "Timestamp position", "description": "Position of the timestamp on the image (tl/tr/bl/br)." diff --git a/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx b/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx index d77d8dccd..4e1dba1fd 100644 --- a/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx +++ b/web/src/components/config-form/theme/templates/ObjectFieldTemplate.tsx @@ -30,7 +30,18 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) { const [isOpen, setIsOpen] = useState(true); - const { t } = useTranslation([formContext?.i18nNamespace || "common"]); + const { t } = useTranslation([ + formContext?.i18nNamespace || "common", + "config/groups", + ]); + + // Extract domain from i18nNamespace (e.g., "config/audio" -> "audio") + const getDomainFromNamespace = (ns?: string): string => { + if (!ns || !ns.startsWith("config/")) return ""; + return ns.replace("config/", ""); + }; + + const domain = getDomainFromNamespace(formContext?.i18nNamespace); const groupDefinitions = (uiSchema?.["ui:groups"] as Record | undefined) || {}; @@ -120,9 +131,14 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) { ordered.forEach((item) => grouped.add(item.name)); - const label = t(`groups.${groupKey}`, { - defaultValue: toTitle(groupKey), - }); + const label = domain + ? t(`${domain}.${groupKey}`, { + ns: "config/groups", + defaultValue: toTitle(groupKey), + }) + : t(`groups.${groupKey}`, { + defaultValue: toTitle(groupKey), + }); return { key: groupKey, diff --git a/web/src/utils/i18n.ts b/web/src/utils/i18n.ts index 16735fbdb..c31d3984a 100644 --- a/web/src/utils/i18n.ts +++ b/web/src/utils/i18n.ts @@ -73,6 +73,7 @@ i18n "config/face_recognition", "config/lpr", "config/validation", + "config/groups", ], defaultNS: "common",