Use translations

This commit is contained in:
0x464e 2026-03-19 19:30:13 +02:00
parent 9524f8c4e5
commit 5639fdfd6a
No known key found for this signature in database
GPG Key ID: E6D221DF6CBFBFFA
6 changed files with 51 additions and 20 deletions

View File

@ -131,6 +131,8 @@
"close": "Close", "close": "Close",
"copy": "Copy", "copy": "Copy",
"copiedToClipboard": "Copied to clipboard", "copiedToClipboard": "Copied to clipboard",
"shareTimestamp": "Share Timestamp",
"shareTimestampUrl": "Share Timestamp URL",
"back": "Back", "back": "Back",
"history": "History", "history": "History",
"fullscreen": "Fullscreen", "fullscreen": "Fullscreen",

View File

@ -99,6 +99,14 @@
} }
}, },
"recording": { "recording": {
"shareTimestamp": {
"title": "Share Review Timestamp",
"description": "Share the current player position or choose a custom timestamp.",
"current": "Current Player Timestamp",
"custom": "Custom Timestamp",
"customDescription": "Pick a specific point in time to share.",
"shareTitle": "Frigate Review Timestamp: {{camera}}"
},
"confirmDelete": { "confirmDelete": {
"title": "Confirm Delete", "title": "Confirm Delete",
"desc": { "desc": {

View File

@ -18,7 +18,7 @@ export default function ActionsDropdown({
onDebugReplayClick, onDebugReplayClick,
onExportClick, onExportClick,
onShareTimestampClick, onShareTimestampClick,
}: ActionsDropdownProps) { }: Readonly<ActionsDropdownProps>) {
const { t } = useTranslation(["components/dialog", "views/replay", "common"]); const { t } = useTranslation(["components/dialog", "views/replay", "common"]);
return ( return (
@ -40,7 +40,7 @@ export default function ActionsDropdown({
{t("menu.export", { ns: "common" })} {t("menu.export", { ns: "common" })}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={onShareTimestampClick}> <DropdownMenuItem onClick={onShareTimestampClick}>
Share Timestamp {t("button.shareTimestamp", { ns: "common" })}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem onClick={onDebugReplayClick}> <DropdownMenuItem onClick={onDebugReplayClick}>
{t("title", { ns: "views/replay" })} {t("title", { ns: "views/replay" })}

View File

@ -104,6 +104,7 @@ export default function MobileReviewSettingsDrawer({
"views/recording", "views/recording",
"components/dialog", "components/dialog",
"views/replay", "views/replay",
"common",
]); ]);
const navigate = useNavigate(); const navigate = useNavigate();
const [drawerMode, setDrawerMode] = useState<DrawerMode>("none"); const [drawerMode, setDrawerMode] = useState<DrawerMode>("none");
@ -283,14 +284,14 @@ export default function MobileReviewSettingsDrawer({
{features.includes("share-timestamp") && ( {features.includes("share-timestamp") && (
<Button <Button
className="flex w-full items-center justify-center gap-2" className="flex w-full items-center justify-center gap-2"
aria-label="Share timestamp" aria-label={t("button.shareTimestamp", { ns: "common" })}
onClick={() => { onClick={() => {
setDrawerMode("none"); setDrawerMode("none");
onShareTimestampClick(); onShareTimestampClick();
}} }}
> >
<LuShare2 className="size-5 rounded-md bg-secondary-foreground stroke-secondary p-1" /> <LuShare2 className="size-5 rounded-md bg-secondary-foreground stroke-secondary p-1" />
Share Timestamp {t("button.shareTimestamp", { ns: "common" })}
</Button> </Button>
)} )}
{features.includes("calendar") && ( {features.includes("calendar") && (

View File

@ -111,8 +111,8 @@ function ShareTimestampContent({
customTimestamp, customTimestamp,
setCustomTimestamp, setCustomTimestamp,
onShareTimestamp, onShareTimestamp,
}: ShareTimestampContentProps) { }: Readonly<ShareTimestampContentProps>) {
const { t } = useTranslation(["common"]); const { t } = useTranslation(["common", "components/dialog"]);
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
const currentTimestampLabel = useFormattedTimestamp( const currentTimestampLabel = useFormattedTimestamp(
currentTime, currentTime,
@ -127,9 +127,13 @@ function ShareTimestampContent({
return ( return (
<div className="w-full"> <div className="w-full">
<div className="space-y-1"> <div className="space-y-1">
<div className="text-sm font-medium">Share Review Timestamp</div> <div className="text-sm font-medium">
{t("recording.shareTimestamp.title", { ns: "components/dialog" })}
</div>
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
Share the current player position or choose a custom timestamp. {t("recording.shareTimestamp.description", {
ns: "components/dialog",
})}
</div> </div>
</div> </div>
@ -145,7 +149,9 @@ function ShareTimestampContent({
<RadioGroupItem id="share-current" value="current" /> <RadioGroupItem id="share-current" value="current" />
<Label className="cursor-pointer space-y-1" htmlFor="share-current"> <Label className="cursor-pointer space-y-1" htmlFor="share-current">
<div className="text-sm font-medium"> <div className="text-sm font-medium">
Current Player Timestamp {t("recording.shareTimestamp.current", {
ns: "components/dialog",
})}
</div> </div>
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
{currentTimestampLabel} {currentTimestampLabel}
@ -158,9 +164,15 @@ function ShareTimestampContent({
<div className="flex items-start gap-2"> <div className="flex items-start gap-2">
<RadioGroupItem id="share-custom" value="custom" /> <RadioGroupItem id="share-custom" value="custom" />
<Label className="cursor-pointer space-y-1" htmlFor="share-custom"> <Label className="cursor-pointer space-y-1" htmlFor="share-custom">
<div className="text-sm font-medium">Custom Timestamp</div> <div className="text-sm font-medium">
{t("recording.shareTimestamp.custom", {
ns: "components/dialog",
})}
</div>
<div className="text-sm text-muted-foreground"> <div className="text-sm text-muted-foreground">
Pick a specific point in time to share. {t("recording.shareTimestamp.customDescription", {
ns: "components/dialog",
})}
</div> </div>
</Label> </Label>
</div> </div>
@ -168,7 +180,9 @@ function ShareTimestampContent({
<CustomTimestampSelector <CustomTimestampSelector
timestamp={customTimestamp} timestamp={customTimestamp}
setTimestamp={setCustomTimestamp} setTimestamp={setCustomTimestamp}
label="Custom Timestamp" label={t("recording.shareTimestamp.custom", {
ns: "components/dialog",
})}
/> />
)} )}
</div> </div>
@ -180,7 +194,7 @@ function ShareTimestampContent({
variant="select" variant="select"
onClick={() => onShareTimestamp(Math.floor(selectedTimestamp))} onClick={() => onShareTimestamp(Math.floor(selectedTimestamp))}
> >
<span>Share Timestamp Link</span> <span>{t("button.shareTimestampUrl", { ns: "common" })}</span>
<LuShare2 className="size-4" /> <LuShare2 className="size-4" />
</Button> </Button>
</div> </div>
@ -198,7 +212,7 @@ function CustomTimestampSelector({
timestamp, timestamp,
setTimestamp, setTimestamp,
label, label,
}: CustomTimestampSelectorProps) { }: Readonly<CustomTimestampSelectorProps>) {
const { t } = useTranslation(["common"]); const { t } = useTranslation(["common"]);
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
@ -310,9 +324,9 @@ function CustomTimestampSelector({
: nextClock.split(":"); : nextClock.split(":");
const nextTimestamp = new Date(displayTimestamp * 1000); const nextTimestamp = new Date(displayTimestamp * 1000);
nextTimestamp.setHours( nextTimestamp.setHours(
parseInt(hour), Number.parseInt(hour),
parseInt(minute), Number.parseInt(minute),
parseInt(second ?? "0"), Number.parseInt(second ?? "0"),
0, 0,
); );
setFromDisplayDate(nextTimestamp); setFromDisplayDate(nextTimestamp);

View File

@ -107,7 +107,7 @@ export function RecordingView({
updateFilter, updateFilter,
refreshData, refreshData,
}: RecordingViewProps) { }: RecordingViewProps) {
const { t } = useTranslation(["views/events"]); const { t } = useTranslation(["views/events", "components/dialog"]);
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
@ -344,9 +344,15 @@ export function RecordingView({
config?.ui.timezone, config?.ui.timezone,
); );
shareOrCopy(reviewUrl, `Frigate Review Timestamp: ${mainCamera}`); shareOrCopy(
reviewUrl,
t("recording.shareTimestamp.shareTitle", {
ns: "components/dialog",
camera: mainCamera,
}),
);
}, },
[location.pathname, mainCamera, config?.ui.timezone], [location.pathname, mainCamera, config?.ui.timezone, t],
); );
useEffect(() => { useEffect(() => {