From c2183bd850950b421c0962ea839caffa46495aae Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sun, 12 Oct 2025 12:51:23 -0500 Subject: [PATCH] add i18n and popover for brand url --- web/public/locales/en/views/settings.json | 14 +++++-- .../components/settings/Step1NameCamera.tsx | 41 ++++++++++++++++--- .../components/settings/Step2StreamConfig.tsx | 2 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index cb3cb1f9e..627326cd2 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -164,7 +164,7 @@ "step1": { "description": "Enter your camera details and test the connection.", "cameraName": "Camera Name", - "cameraNamePlaceholder": "e.g., front_door", + "cameraNamePlaceholder": "e.g., front_door or Back Yard Overview", "host": "Host/IP Address", "port": "Port", "username": "Username", @@ -175,6 +175,8 @@ "cameraBrand": "Camera Brand", "selectBrand": "Select camera brand for URL template", "customUrl": "Custom Stream URL", + "brandInformation": "Brand information", + "brandUrlFormat": "For cameras with the RTSP URL format as: {{exampleUrl}}", "customUrlPlaceholder": "rtsp://username:password@host:port/path", "testConnection": "Test Connection", "testSuccess": "Connection test successful!", @@ -184,7 +186,11 @@ "noSnapshot": "Unable to fetch a snapshot from the configured stream." }, "errors": { - "brandOrCustomUrlRequired": "Either select a camera brand with host/IP or choose 'Other' with a custom URL" + "brandOrCustomUrlRequired": "Either select a camera brand with host/IP or choose 'Other' with a custom URL", + "nameRequired": "Camera name is required", + "nameLength": "Camera name must be 64 characters or less", + "invalidCharacters": "Camera name contains invalid characters", + "nameExists": "Camera name already exists" } }, "step2": { @@ -292,8 +298,8 @@ "description": "Configure camera settings including stream inputs and roles.", "name": "Camera Name", "nameRequired": "Camera name is required", - "nameLength": "Camera name must be less than 24 characters.", - "namePlaceholder": "e.g., front_door", + "nameLength": "Camera name must be less than 64 characters.", + "namePlaceholder": "e.g., front_door or Back Yard Overview", "enabled": "Enabled", "ffmpeg": { "inputs": "Input Streams", diff --git a/web/src/components/settings/Step1NameCamera.tsx b/web/src/components/settings/Step1NameCamera.tsx index c99b3ba04..01f3b70ad 100644 --- a/web/src/components/settings/Step1NameCamera.tsx +++ b/web/src/components/settings/Step1NameCamera.tsx @@ -39,6 +39,12 @@ import { } from "@/types/cameraWizard"; import { FaCircleCheck } from "react-icons/fa6"; import { Card, CardContent, CardTitle } from "../ui/card"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { LuInfo } from "react-icons/lu"; type Step1NameCameraProps = { wizardData: Partial; @@ -71,12 +77,15 @@ export default function Step1NameCamera({ .object({ cameraName: z .string() - .min(1, "Camera name is required") - .max(64, "Camera name must be 64 characters or less") - .regex(/^[a-zA-Z0-9\s_-]+$/, "Camera name contains invalid characters") + .min(1, t("cameraWizard.step1.errors.nameRequired")) + .max(64, t("cameraWizard.step1.errors.nameLength")) + .regex( + /^[a-zA-Z0-9\s_-]+$/, + t("cameraWizard.step1.errors.invalidCharacters"), + ) .refine( (value) => !existingCameraNames.includes(value), - "Camera name already exists", + t("cameraWizard.step1.errors.nameExists"), ), host: z.string().optional(), username: z.string().optional(), @@ -357,9 +366,29 @@ export default function Step1NameCamera({ const selectedBrand = CAMERA_BRANDS.find( (brand) => brand.value === field.value, ); - return selectedBrand ? ( + return selectedBrand && + selectedBrand.value != "other" ? ( - {selectedBrand.exampleUrl} + + +
+ + {t("cameraWizard.step1.brandInformation")} +
+
+ +
+

+ {selectedBrand.label} +

+

+ {t("cameraWizard.step1.brandUrlFormat", { + exampleUrl: selectedBrand.exampleUrl, + })} +

+
+
+
) : null; })()} diff --git a/web/src/components/settings/Step2StreamConfig.tsx b/web/src/components/settings/Step2StreamConfig.tsx index c33c35d6f..03bc6dbc1 100644 --- a/web/src/components/settings/Step2StreamConfig.tsx +++ b/web/src/components/settings/Step2StreamConfig.tsx @@ -226,7 +226,7 @@ export default function Step2StreamConfig({ {[ stream.testResult.resolution, stream.testResult.fps - ? `${stream.testResult.fps} fps` + ? `${stream.testResult.fps} ${t("cameraWizard.testResultLabels.fps")}` : null, stream.testResult.videoCodec, stream.testResult.audioCodec,