mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-02 17:12:16 +03:00
Refactor and clean up i18n (#17198)
* clean up i18n * fix key * fix key
This commit is contained in:
@@ -128,7 +128,7 @@ export default function CreateUserDialog({
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium">
|
||||
{t("users.dialog.form.user")}
|
||||
{t("users.dialog.form.user.title")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -150,7 +150,7 @@ export default function CreateUserDialog({
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium">
|
||||
{t("users.dialog.form.password")}
|
||||
{t("users.dialog.form.password.title")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
@@ -170,7 +170,7 @@ export default function CreateUserDialog({
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="text-sm font-medium">
|
||||
{t("users.dialog.form.password.confirm")}
|
||||
{t("users.dialog.form.password.confirm.title")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
|
||||
@@ -267,7 +267,7 @@ export function ExportContent({
|
||||
{isDesktop && (
|
||||
<>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("menu.export")}</DialogTitle>
|
||||
<DialogTitle>{t("menu.export", { ns: "common" })}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<SelectSeparator className="my-4 bg-secondary" />
|
||||
</>
|
||||
@@ -404,14 +404,14 @@ function CustomTimeSelector({
|
||||
const formattedStart = useFormattedTimestamp(
|
||||
startTime,
|
||||
config?.ui.time_format == "24hour"
|
||||
? t("time.formattedTimestamp.24hour")
|
||||
: t("time.formattedTimestamp"),
|
||||
? t("time.formattedTimestamp.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestamp.12hour", { ns: "common" }),
|
||||
);
|
||||
const formattedEnd = useFormattedTimestamp(
|
||||
endTime,
|
||||
config?.ui.time_format == "24hour"
|
||||
? t("time.formattedTimestamp.24hour")
|
||||
: t("time.formattedTimestamp"),
|
||||
? t("time.formattedTimestamp.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestamp.12hour", { ns: "common" }),
|
||||
);
|
||||
|
||||
const startClock = useMemo(() => {
|
||||
@@ -444,7 +444,7 @@ function CustomTimeSelector({
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
className={`text-primary ${isDesktop ? "" : "text-xs"}`}
|
||||
aria-label={t("export.time.start")}
|
||||
aria-label={t("export.time.start.title")}
|
||||
variant={startOpen ? "select" : "default"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
@@ -510,7 +510,7 @@ function CustomTimeSelector({
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
className={`text-primary ${isDesktop ? "" : "text-xs"}`}
|
||||
aria-label={t("export.time.end")}
|
||||
aria-label={t("export.time.end.title")}
|
||||
variant={endOpen ? "select" : "default"}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function MobileCameraDrawer({
|
||||
<DrawerTrigger asChild>
|
||||
<Button
|
||||
className="rounded-lg capitalize"
|
||||
aria-label={t("menu.live.cameras")}
|
||||
aria-label={t("menu.live.cameras.title")}
|
||||
size="sm"
|
||||
>
|
||||
<FaVideo className="text-secondary-foreground" />
|
||||
|
||||
@@ -19,7 +19,6 @@ import { toast } from "sonner";
|
||||
import axios from "axios";
|
||||
import SaveExportOverlay from "./SaveExportOverlay";
|
||||
import { isIOS, isMobile } from "react-device-detect";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type DrawerMode = "none" | "select" | "export" | "calendar" | "filter";
|
||||
@@ -70,7 +69,7 @@ export default function MobileReviewSettingsDrawer({
|
||||
setMode,
|
||||
setShowExportPreview,
|
||||
}: MobileReviewSettingsDrawerProps) {
|
||||
const { t } = useTranslation(["views/recording"]);
|
||||
const { t } = useTranslation(["views/recording", "components/dialog"]);
|
||||
const [drawerMode, setDrawerMode] = useState<DrawerMode>("none");
|
||||
|
||||
// exports
|
||||
|
||||
@@ -68,13 +68,13 @@ export default function RoleChangeDialog({
|
||||
<SelectItem value="admin" className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<LuShield className="size-4 text-primary" />
|
||||
<span>{t("role.admin")}</span>
|
||||
<span>{t("role.admin", { ns: "common" })}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="viewer" className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<LuUser className="size-4 text-primary" />
|
||||
<span>{t("role.viewer")}</span>
|
||||
<span>{t("role.viewer", { ns: "common" })}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
|
||||
@@ -117,7 +117,7 @@ export default function SetPasswordDialog({
|
||||
<div className="space-y-4 py-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">
|
||||
{t("users.dialog.form.newPassword")}
|
||||
{t("users.dialog.form.newPassword.title")}
|
||||
</Label>
|
||||
<Input
|
||||
id="password"
|
||||
@@ -142,7 +142,7 @@ export default function SetPasswordDialog({
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t("users.dialog.form.password.strength")}
|
||||
{t("users.dialog.form.password.strength.title")}
|
||||
<span className="font-medium">{getStrengthLabel()}</span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -151,7 +151,7 @@ export default function SetPasswordDialog({
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="confirm-password">
|
||||
{t("users.dialog.form.password.confirm")}
|
||||
{t("users.dialog.form.password.confirm.title")}
|
||||
</Label>
|
||||
<Input
|
||||
id="confirm-password"
|
||||
|
||||
@@ -85,7 +85,7 @@ export function AnnotationSettingsPane({
|
||||
updateConfig();
|
||||
} else {
|
||||
toast.error(
|
||||
t("toast.save.error", {
|
||||
t("toast.save.error.title", {
|
||||
errorMessage: res.statusText,
|
||||
ns: "common",
|
||||
}),
|
||||
@@ -100,9 +100,12 @@ export function AnnotationSettingsPane({
|
||||
error.response?.data?.message ||
|
||||
error.response?.data?.detail ||
|
||||
"Unknown error";
|
||||
toast.error(t("toast.save.error", { errorMessage, ns: "common" }), {
|
||||
position: "top-center",
|
||||
});
|
||||
toast.error(
|
||||
t("toast.save.error.title", { errorMessage, ns: "common" }),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
@@ -145,7 +148,7 @@ export function AnnotationSettingsPane({
|
||||
onCheckedChange={setShowZones}
|
||||
/>
|
||||
<Label className="cursor-pointer" htmlFor="show-zones">
|
||||
{t("objectLifecycle.annotationSettings.showAllZones")}
|
||||
{t("objectLifecycle.annotationSettings.showAllZones.title")}
|
||||
</Label>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
|
||||
@@ -573,7 +573,7 @@ export default function ObjectLifecycle({
|
||||
? t("time.formattedTimestamp2.24hour", {
|
||||
ns: "common",
|
||||
})
|
||||
: t("time.formattedTimestamp2", {
|
||||
: t("time.formattedTimestamp2.12hour", {
|
||||
ns: "common",
|
||||
}),
|
||||
time_style: "medium",
|
||||
|
||||
@@ -98,7 +98,7 @@ export default function ReviewDetailDialog({
|
||||
review?.start_time ?? 0,
|
||||
config?.ui.time_format == "24hour"
|
||||
? t("time.formattedTimestampWithYear.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestampWithYear", { ns: "common" }),
|
||||
: t("time.formattedTimestampWithYear.12hour", { ns: "common" }),
|
||||
config?.ui.timezone,
|
||||
);
|
||||
|
||||
|
||||
@@ -195,7 +195,9 @@ export default function SearchDetailDialog({
|
||||
>
|
||||
<Header>
|
||||
<Title>{t("trackedObjectDetails")}</Title>
|
||||
<Description className="sr-only">{t("details")}</Description>
|
||||
<Description className="sr-only">
|
||||
{t("trackedObjectDetails")}
|
||||
</Description>
|
||||
</Header>
|
||||
<ScrollArea
|
||||
className={cn("w-full whitespace-nowrap", isMobile && "my-2")}
|
||||
@@ -311,7 +313,7 @@ function ObjectDetailsTab({
|
||||
search?.start_time ?? 0,
|
||||
config?.ui.time_format == "24hour"
|
||||
? t("time.formattedTimestampWithYear.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestampWithYear", { ns: "common" }),
|
||||
: t("time.formattedTimestampWithYear.12hour", { ns: "common" }),
|
||||
config?.ui.timezone,
|
||||
);
|
||||
|
||||
@@ -575,7 +577,9 @@ function ObjectDetailsTab({
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
<TooltipContent>{t("details.editSubLable")}</TooltipContent>
|
||||
<TooltipContent>
|
||||
{t("details.editSubLabel.title")}
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@@ -597,7 +601,7 @@ function ObjectDetailsTab({
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<div className="text-sm text-primary/40">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
{t("details.topScore")}
|
||||
{t("details.topScore.label")}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<div className="cursor-pointer p-0">
|
||||
@@ -727,7 +731,7 @@ function ObjectDetailsTab({
|
||||
aria-label={t("details.button.regenerate.label")}
|
||||
onClick={() => regenerateDescription("thumbnails")}
|
||||
>
|
||||
{t("details.button.regenerate")}
|
||||
{t("details.button.regenerate.title")}
|
||||
</Button>
|
||||
{search.has_snapshot && (
|
||||
<DropdownMenu>
|
||||
@@ -772,13 +776,13 @@ function ObjectDetailsTab({
|
||||
<TextEntryDialog
|
||||
open={isSubLabelDialogOpen}
|
||||
setOpen={setIsSubLabelDialogOpen}
|
||||
title={t("details.editSubLable")}
|
||||
title={t("details.editSubLabel.title")}
|
||||
description={
|
||||
search.label
|
||||
? t("details.editSubLable.desc", {
|
||||
label: t(search.label, { ns: "objects" }),
|
||||
? t("details.editSubLabel.desc", {
|
||||
label: t(search.label, { an: "objects" }),
|
||||
})
|
||||
: t("details.editSubLable.desc.noLabel")
|
||||
: t("details.editSubLabel.descNoLabel")
|
||||
}
|
||||
onSave={handleSubLabelSave}
|
||||
defaultValue={search?.sub_label || ""}
|
||||
@@ -921,10 +925,10 @@ export function ObjectSnapshotTab({
|
||||
}}
|
||||
>
|
||||
{/^[aeiou]/i.test(search?.label || "")
|
||||
? t("explore.plus.review.true_other", {
|
||||
? t("explore.plus.review.true.true_other", {
|
||||
label: search?.label,
|
||||
})
|
||||
: t("explore.plus.review.true_one", {
|
||||
: t("explore.plus.review.true.true_one", {
|
||||
label: search?.label,
|
||||
})}
|
||||
</Button>
|
||||
@@ -938,10 +942,10 @@ export function ObjectSnapshotTab({
|
||||
}}
|
||||
>
|
||||
{/^[aeiou]/i.test(search?.label || "")
|
||||
? t("explore.plus.review.false_other", {
|
||||
? t("explore.plus.review.false.false_other", {
|
||||
label: search?.label,
|
||||
})
|
||||
: t("explore.plus.review.false_one", {
|
||||
: t("explore.plus.review.false.false_one", {
|
||||
label: search?.label,
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -251,7 +251,7 @@ function TimeRangeFilterContent({
|
||||
timeRange,
|
||||
updateTimeRange,
|
||||
}: TimeRangeFilterContentProps) {
|
||||
const { t } = useTranslation(["components/filter"]);
|
||||
const { t } = useTranslation(["components/filter", "components/dialog"]);
|
||||
const [startOpen, setStartOpen] = useState(false);
|
||||
const [endOpen, setEndOpen] = useState(false);
|
||||
|
||||
@@ -406,7 +406,7 @@ export function ZoneFilterContent({
|
||||
className="mx-2 cursor-pointer text-primary"
|
||||
htmlFor="allZones"
|
||||
>
|
||||
{t("zones.all")}
|
||||
{t("zones.all.title")}
|
||||
</Label>
|
||||
<Switch
|
||||
className="ml-1"
|
||||
@@ -581,6 +581,7 @@ export function SpeedFilterContent({
|
||||
<DropdownMenuSeparator className="mb-3" />
|
||||
<div className="mb-3 text-lg">
|
||||
{t("estimatedSpeed", {
|
||||
ns: "components/filter",
|
||||
unit:
|
||||
config?.ui.unit_system == "metric"
|
||||
? t("unit.speed.kph", { ns: "common" })
|
||||
|
||||
Reference in New Issue
Block a user