mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 05:24:11 +03:00
Fix I18n audio labels (#20508)
* ensure i18n audio label keys are translated don't assume they are in the objects namespace * add missing audio labels * Improve handling of label types * simplify * fixes --------- Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
parent
e592c7044b
commit
75d7049b6d
@ -425,5 +425,79 @@
|
||||
"television": "Television",
|
||||
"radio": "Radio",
|
||||
"field_recording": "Field Recording",
|
||||
"scream": "Scream"
|
||||
"scream": "Scream",
|
||||
"sodeling": "Sodeling",
|
||||
"chird": "Chird",
|
||||
"change_ringing": "Change Ringing",
|
||||
"shofar": "Shofar",
|
||||
"liquid": "Liquid",
|
||||
"splash": "Splash",
|
||||
"slosh": "Slosh",
|
||||
"squish": "Squish",
|
||||
"drip": "Drip",
|
||||
"pour": "Pour",
|
||||
"trickle": "Trickle",
|
||||
"gush": "Gush",
|
||||
"fill": "Fill",
|
||||
"spray": "Spray",
|
||||
"pump": "Pump",
|
||||
"stir": "Stir",
|
||||
"boiling": "Boiling",
|
||||
"sonar": "Sonar",
|
||||
"arrow": "Arrow",
|
||||
"whoosh": "Whoosh",
|
||||
"thump": "Thump",
|
||||
"thunk": "Thunk",
|
||||
"electronic_tuner": "Electronic Tuner",
|
||||
"effects_unit": "Effects Unit",
|
||||
"chorus_effect": "Chorus Effect",
|
||||
"basketball_bounce": "Basketball Bounce",
|
||||
"bang": "Bang",
|
||||
"slap": "Slap",
|
||||
"whack": "Whack",
|
||||
"smash": "Smash",
|
||||
"breaking": "Breaking",
|
||||
"bouncing": "Bouncing",
|
||||
"whip": "Whip",
|
||||
"flap": "Flap",
|
||||
"scratch": "Scratch",
|
||||
"scrape": "Scrape",
|
||||
"rub": "Rub",
|
||||
"roll": "Roll",
|
||||
"crushing": "Crushing",
|
||||
"crumpling": "Crumpling",
|
||||
"tearing": "Tearing",
|
||||
"beep": "Beep",
|
||||
"ping": "Ping",
|
||||
"ding": "Ding",
|
||||
"clang": "Clang",
|
||||
"squeal": "Squeal",
|
||||
"creak": "Creak",
|
||||
"rustle": "Rustle",
|
||||
"whir": "Whir",
|
||||
"clatter": "Clatter",
|
||||
"sizzle": "Sizzle",
|
||||
"clicking": "Clicking",
|
||||
"clickety_clack": "Clickety Clack",
|
||||
"rumble": "Rumble",
|
||||
"plop": "Plop",
|
||||
"hum": "Hum",
|
||||
"zing": "Zing",
|
||||
"boing": "Boing",
|
||||
"crunch": "Crunch",
|
||||
"sine_wave": "Sine Wave",
|
||||
"harmonic": "Harmonic",
|
||||
"chirp_tone": "Chirp Tone",
|
||||
"pulse": "Pulse",
|
||||
"inside": "Inside",
|
||||
"outside": "Outside",
|
||||
"reverberation": "Reverberation",
|
||||
"echo": "Echo",
|
||||
"noise": "Noise",
|
||||
"mains_hum": "Mains Hum",
|
||||
"distortion": "Distortion",
|
||||
"sidetone": "Sidetone",
|
||||
"cacophony": "Cacophony",
|
||||
"throbbing": "Throbbing",
|
||||
"vibration": "Vibration"
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ export default function SearchThumbnail({
|
||||
.filter(
|
||||
(item) => item !== undefined && !item.includes("-verified"),
|
||||
)
|
||||
.map((text) => getTranslatedLabel(text))
|
||||
.map((text) => getTranslatedLabel(text, searchResult.data.type))
|
||||
.sort()
|
||||
.join(", ")
|
||||
.replaceAll("-verified", "")}
|
||||
|
||||
@ -29,6 +29,8 @@ export type SearchSortType =
|
||||
| "score_desc"
|
||||
| "relevance";
|
||||
|
||||
export type EventType = "object" | "audio" | "manual";
|
||||
|
||||
export type SearchResult = {
|
||||
id: string;
|
||||
camera: string;
|
||||
@ -54,7 +56,7 @@ export type SearchResult = {
|
||||
box: number[];
|
||||
area: number;
|
||||
ratio: number;
|
||||
type: "object" | "audio" | "manual";
|
||||
type: EventType;
|
||||
description?: string;
|
||||
average_estimated_speed: number;
|
||||
velocity_angle: number;
|
||||
|
||||
@ -1,11 +1,29 @@
|
||||
import i18n, { t } from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import HttpBackend from "i18next-http-backend";
|
||||
import { EventType } from "@/types/search";
|
||||
|
||||
export const getTranslatedLabel = (label: string) => {
|
||||
export const getTranslatedLabel = (
|
||||
label: string,
|
||||
type: EventType = "object",
|
||||
) => {
|
||||
if (!label) return "";
|
||||
|
||||
return t(`${label.replace(/\s+/g, "_").toLowerCase()}`, { ns: "objects" });
|
||||
if (type === "manual") return label;
|
||||
|
||||
const normalize = (s: string) =>
|
||||
s
|
||||
.trim()
|
||||
.replace(/[-'\s]+/g, "_")
|
||||
.replace(/__+/g, "_")
|
||||
.replace(/^_+|_+$/g, "")
|
||||
.toLowerCase();
|
||||
|
||||
const key = normalize(label);
|
||||
|
||||
const ns = type === "audio" ? "audio" : "objects";
|
||||
|
||||
return t(key, { ns });
|
||||
};
|
||||
|
||||
i18n
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
||||
import { SearchResult } from "@/types/search";
|
||||
import { EventType, SearchResult } from "@/types/search";
|
||||
import ImageLoadingIndicator from "@/components/indicators/ImageLoadingIndicator";
|
||||
import useImageLoaded from "@/hooks/use-image-loaded";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
@ -110,7 +110,8 @@ export default function ExploreView({
|
||||
key={label}
|
||||
searchResults={filteredEvents}
|
||||
isValidating={isValidating}
|
||||
objectType={label}
|
||||
label={label}
|
||||
labelType={filteredEvents[0]?.data?.type || "object"}
|
||||
setSearchDetail={setSearchDetail}
|
||||
mutate={mutate}
|
||||
setSimilaritySearch={setSimilaritySearch}
|
||||
@ -122,7 +123,8 @@ export default function ExploreView({
|
||||
}
|
||||
|
||||
type ThumbnailRowType = {
|
||||
objectType: string;
|
||||
label: string;
|
||||
labelType: EventType;
|
||||
searchResults?: SearchResult[];
|
||||
isValidating: boolean;
|
||||
setSearchDetail: (search: SearchResult | undefined) => void;
|
||||
@ -132,7 +134,8 @@ type ThumbnailRowType = {
|
||||
};
|
||||
|
||||
function ThumbnailRow({
|
||||
objectType,
|
||||
label,
|
||||
labelType,
|
||||
searchResults,
|
||||
isValidating,
|
||||
setSearchDetail,
|
||||
@ -153,7 +156,7 @@ function ThumbnailRow({
|
||||
return (
|
||||
<div className="rounded-lg bg-background_alt p-2 md:px-4">
|
||||
<div className="flex flex-row items-center text-lg smart-capitalize">
|
||||
{getTranslatedLabel(objectType)}
|
||||
{getTranslatedLabel(label, labelType)}
|
||||
{searchResults && (
|
||||
<span className="ml-3 text-sm text-secondary-foreground">
|
||||
{t("trackedObjectsCount", {
|
||||
@ -181,7 +184,7 @@ function ThumbnailRow({
|
||||
))}
|
||||
<div
|
||||
className="flex cursor-pointer items-center justify-center"
|
||||
onClick={() => handleSearch(objectType)}
|
||||
onClick={() => handleSearch(label)}
|
||||
>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
@ -192,7 +195,9 @@ function ThumbnailRow({
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
<TooltipContent>
|
||||
{t("exploreMore", { label: getTranslatedLabel(objectType) })}
|
||||
{t("exploreMore", {
|
||||
label: getTranslatedLabel(label, labelType),
|
||||
})}
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
</Tooltip>
|
||||
|
||||
@ -100,7 +100,12 @@ export default function CameraSettingsView({
|
||||
const alertsLabels = useMemo(() => {
|
||||
return cameraConfig?.review.alerts.labels
|
||||
? cameraConfig.review.alerts.labels
|
||||
.map((label) => getTranslatedLabel(label))
|
||||
.map((label) =>
|
||||
getTranslatedLabel(
|
||||
label,
|
||||
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
||||
),
|
||||
)
|
||||
.join(", ")
|
||||
: "";
|
||||
}, [cameraConfig]);
|
||||
@ -108,7 +113,12 @@ export default function CameraSettingsView({
|
||||
const detectionsLabels = useMemo(() => {
|
||||
return cameraConfig?.review.detections.labels
|
||||
? cameraConfig.review.detections.labels
|
||||
.map((label) => getTranslatedLabel(label))
|
||||
.map((label) =>
|
||||
getTranslatedLabel(
|
||||
label,
|
||||
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
||||
),
|
||||
)
|
||||
.join(", ")
|
||||
: "";
|
||||
}, [cameraConfig]);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user