mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-05 13:07:44 +03:00
feat: add explore model i18n keys
This commit is contained in:
parent
118ef6b2fe
commit
84ba218b1b
@ -111,6 +111,7 @@
|
||||
"restart": "Restart Frigate",
|
||||
"live": "Live",
|
||||
"live.allCameras": "All Cameras",
|
||||
"live.cameras": "Cameras",
|
||||
"review": "Review",
|
||||
"explore": "Explore",
|
||||
"export": "Export",
|
||||
|
||||
@ -1,4 +1,32 @@
|
||||
{
|
||||
"exploreIsUnavailable": {
|
||||
"title": "Explore is Unavailable",
|
||||
"embeddingsReindexing": {
|
||||
"context": "Explore can be used after tracked object embeddings have finished reindexing.",
|
||||
"startingUp": "Starting up...",
|
||||
"estimatedTime": "Estimated time remaining:",
|
||||
"finishingShortly": "Finishing shortly",
|
||||
"step": {
|
||||
"thumbnailsEmbedded": "Thumbnails embedded: ",
|
||||
"descriptionsEmbedded": "Descriptions embedded: ",
|
||||
"trackedObjectsProcessed": "Tracked objects processed: "
|
||||
}
|
||||
},
|
||||
"downloadingModels": {
|
||||
"context": "Frigate is downloading the necessary embeddings models to support the Semantic Search feature. This may take several minutes depending on the speed of your network connection.",
|
||||
"setup": {
|
||||
"visionModel": "Vision model",
|
||||
"visionModelFeatureExtractor": "Vision model feature extractor",
|
||||
"textModel": "Text model",
|
||||
"textTokenizer": "Text tokenizer"
|
||||
},
|
||||
"tips": {
|
||||
"context": "You may want to reindex the embeddings of your tracked objects once the models are downloaded.",
|
||||
"documentation": "Read the documentation"
|
||||
},
|
||||
"error": "An error has occurred. Check Frigate logs."
|
||||
}
|
||||
},
|
||||
"trackedObjectDetails": "Tracked Object Details",
|
||||
"type": {
|
||||
"details": "details",
|
||||
|
||||
@ -69,6 +69,7 @@
|
||||
"stats": {
|
||||
"ffmpegHighCpuUsage": "{{camera}} has high FFMPEG CPU usage ({{ffmpegAvg}}%)",
|
||||
"detectHighCpuUsage": "{{camera}} has high detect CPU usage ({{detectAvg}}%)",
|
||||
"healthy": "System is healthy"
|
||||
"healthy": "System is healthy",
|
||||
"reindexingEmbeddings": "Reindexing embeddings ({{processed}}% complete)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +110,7 @@
|
||||
"documentation": "文档",
|
||||
"live": "实时监控",
|
||||
"live.allCameras": "所有摄像头",
|
||||
"live.cameras": "摄像头",
|
||||
"review": "回放",
|
||||
"explore": "探测",
|
||||
"export": "导出",
|
||||
|
||||
@ -1,4 +1,32 @@
|
||||
{
|
||||
"exploreIsUnavailable": {
|
||||
"title": "探索功能不可用",
|
||||
"embeddingsReindexing": {
|
||||
"context": "跟踪对象嵌入重新索引完成后,可以使用探索功能。",
|
||||
"startingUp": "启动中...",
|
||||
"estimatedTime": "预计剩余时间:",
|
||||
"finishingShortly": "即将完成",
|
||||
"step": {
|
||||
"thumbnailsEmbedded": "缩略图嵌入:",
|
||||
"descriptionsEmbedded": "描述嵌入:",
|
||||
"trackedObjectsProcessed": "跟踪对象已处理:"
|
||||
}
|
||||
},
|
||||
"downloadingModels": {
|
||||
"context": "Frigate正在下载支持语义搜索功能所需的嵌入模型。根据网络连接速度,这可能需要几分钟。",
|
||||
"setup": {
|
||||
"visionModel": "视觉模型",
|
||||
"visionModelFeatureExtractor": "视觉模型特征提取器",
|
||||
"textModel": "文本模型",
|
||||
"textTokenizer": "文本分词器"
|
||||
},
|
||||
"tips": {
|
||||
"context": "模型下载完成后,您可能需要重新索引跟踪对象的嵌入。",
|
||||
"documentation": "阅读文档(英文)"
|
||||
},
|
||||
"error": "发生错误。请检查Frigate日志。"
|
||||
}
|
||||
},
|
||||
"trackedObjectDetails": "探测对象详情",
|
||||
"type": {
|
||||
"details": "详情",
|
||||
|
||||
@ -69,6 +69,7 @@
|
||||
"stats": {
|
||||
"ffmpegHighCpuUsage": "{{camera}} 的 FFMPEG CPU 使用率较高({{ffmpegAvg}}%)",
|
||||
"detectHighCpuUsage": "{{camera}} 的 探测 CPU 使用率较高({{detectAvg}}%)",
|
||||
"healthy": "系统运行正常"
|
||||
"healthy": "系统运行正常",
|
||||
"reindexingEmbeddings": "正在重新索引嵌入(已完成 {{processed}}%)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,14 +54,19 @@ export default function Statusbar() {
|
||||
clearMessages("embeddings-reindex");
|
||||
addMessage(
|
||||
"embeddings-reindex",
|
||||
`Reindexing embeddings (${Math.floor((reindexState.processed_objects / reindexState.total_objects) * 100)}% complete)`,
|
||||
t("stats.reindexingEmbeddings", {
|
||||
processed: Math.floor(
|
||||
(reindexState.processed_objects / reindexState.total_objects) *
|
||||
100,
|
||||
),
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (reindexState.status === "completed") {
|
||||
clearMessages("embeddings-reindex");
|
||||
}
|
||||
}
|
||||
}, [reindexState, addMessage, clearMessages]);
|
||||
}, [reindexState, addMessage, clearMessages, t]);
|
||||
|
||||
return (
|
||||
<div className="absolute bottom-0 left-0 right-0 z-10 flex h-8 w-full items-center justify-between border-t border-secondary-highlight bg-background_alt px-4 dark:text-secondary-foreground">
|
||||
|
||||
@ -38,7 +38,7 @@ export function CamerasFilterButton({
|
||||
|
||||
const buttonText = useMemo(() => {
|
||||
if (isMobile) {
|
||||
return "Cameras";
|
||||
return t("menu.live.cameras", { ns: "common" });
|
||||
}
|
||||
|
||||
if (!selectedCameras || selectedCameras.length == 0) {
|
||||
|
||||
@ -109,7 +109,7 @@ export default function AccountSettings({ className }: AccountSettingsProps) {
|
||||
{t("menu.user.current", {
|
||||
user: profile?.username || t("menu.user.anonymous"),
|
||||
})}{" "}
|
||||
{t("role." + profile?.role) && `(${t("role." + profile.role)})`}
|
||||
{t("role." + profile?.role) && `(${t("role." + profile?.role)})`}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator className={isDesktop ? "mt-3" : "mt-1"} />
|
||||
{profile?.username && profile.username !== "anonymous" && (
|
||||
|
||||
@ -170,7 +170,7 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
|
||||
user: profile?.username || t("menu.user.anonymous"),
|
||||
})}{" "}
|
||||
{t("role." + profile?.role) &&
|
||||
`(${t("role." + profile.role)})`}
|
||||
`(${t("role." + profile?.role)})`}
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator
|
||||
className={isDesktop ? "mt-3" : "mt-1"}
|
||||
|
||||
@ -15,6 +15,7 @@ import { formatSecondsToDuration } from "@/utils/dateUtil";
|
||||
import SearchView from "@/views/search/SearchView";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { LuCheck, LuExternalLink, LuX } from "react-icons/lu";
|
||||
import { TbExclamationCircle } from "react-icons/tb";
|
||||
import { Link } from "react-router-dom";
|
||||
@ -27,6 +28,8 @@ const API_LIMIT = 25;
|
||||
export default function Explore() {
|
||||
// search field handler
|
||||
|
||||
const { t } = useTranslation(["views/explore"]);
|
||||
|
||||
const { data: config } = useSWR<FrigateConfig>("config", {
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
@ -353,13 +356,12 @@ export default function Explore() {
|
||||
<div className="flex max-w-96 flex-col items-center justify-center space-y-3 rounded-lg bg-background/50 p-5">
|
||||
<div className="my-5 flex flex-col items-center gap-2 text-xl">
|
||||
<TbExclamationCircle className="mb-3 size-10" />
|
||||
<div>Explore is Unavailable</div>
|
||||
<div>{t("exploreIsUnavailable.title")}</div>
|
||||
</div>
|
||||
{embeddingsReindexing && allModelsLoaded && (
|
||||
<>
|
||||
<div className="text-center text-primary-variant">
|
||||
Explore can be used after tracked object embeddings have
|
||||
finished reindexing.
|
||||
{t("exploreIsUnavailable.embeddingsReindexing.context")}
|
||||
</div>
|
||||
<div className="pt-5 text-center">
|
||||
<AnimatedCircularProgressBar
|
||||
@ -375,29 +377,35 @@ export default function Explore() {
|
||||
<div className="mb-3 flex flex-col items-center justify-center gap-1">
|
||||
<div className="text-primary-variant">
|
||||
{reindexState.time_remaining === -1
|
||||
? "Starting up..."
|
||||
: "Estimated time remaining:"}
|
||||
? t(
|
||||
"exploreIsUnavailable.embeddingsReindexing.startingUp",
|
||||
)
|
||||
: t(
|
||||
"exploreIsUnavailable.embeddingsReindexing.estimatedTime",
|
||||
)}
|
||||
</div>
|
||||
{reindexState.time_remaining >= 0 &&
|
||||
(formatSecondsToDuration(reindexState.time_remaining) ||
|
||||
"Finishing shortly")}
|
||||
t(
|
||||
"exploreIsUnavailable.embeddingsReindexing.finishingShortly",
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-row items-center justify-center gap-3">
|
||||
<span className="text-primary-variant">
|
||||
Thumbnails embedded:
|
||||
t("exploreIsUnavailable.embeddingsReindexing.step.thumbnailsEmbedded")
|
||||
</span>
|
||||
{reindexState.thumbnails}
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center gap-3">
|
||||
<span className="text-primary-variant">
|
||||
Descriptions embedded:
|
||||
t("exploreIsUnavailable.embeddingsReindexing.step.descriptionsEmbedded")
|
||||
</span>
|
||||
{reindexState.descriptions}
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center gap-3">
|
||||
<span className="text-primary-variant">
|
||||
Tracked objects processed:
|
||||
t("exploreIsUnavailable.embeddingsReindexing.step.trackedObjectsProcessed")
|
||||
</span>
|
||||
{reindexState.processed_objects} /{" "}
|
||||
{reindexState.total_objects}
|
||||
@ -408,26 +416,32 @@ export default function Explore() {
|
||||
{!allModelsLoaded && (
|
||||
<>
|
||||
<div className="text-center text-primary-variant">
|
||||
Frigate is downloading the necessary embeddings models to
|
||||
support the Semantic Search feature. This may take several
|
||||
minutes depending on the speed of your network connection.
|
||||
{t("exploreIsUnavailable.downloadingModels.context")}
|
||||
</div>
|
||||
<div className="flex w-96 flex-col gap-2 py-5">
|
||||
<div className="flex flex-row items-center justify-center gap-2">
|
||||
{renderModelStateIcon(visionModelState)}
|
||||
Vision model
|
||||
{t(
|
||||
"exploreIsUnavailable.downloadingModels.setup.visionModel",
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center gap-2">
|
||||
{renderModelStateIcon(visionFeatureExtractorState)}
|
||||
Vision model feature extractor
|
||||
{t(
|
||||
"exploreIsUnavailable.downloadingModels.setup.visionModelFeatureExtractor",
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center gap-2">
|
||||
{renderModelStateIcon(textModelState)}
|
||||
Text model
|
||||
{t(
|
||||
"exploreIsUnavailable.downloadingModels.setup.textModel",
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row items-center justify-center gap-2">
|
||||
{renderModelStateIcon(textTokenizerState)}
|
||||
Text tokenizer
|
||||
{t(
|
||||
"exploreIsUnavailable.downloadingModels.setup.textTokenizer",
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{(textModelState === "error" ||
|
||||
@ -435,12 +449,11 @@ export default function Explore() {
|
||||
visionModelState === "error" ||
|
||||
visionFeatureExtractorState === "error") && (
|
||||
<div className="my-3 max-w-96 text-center text-danger">
|
||||
An error has occurred. Check Frigate logs.
|
||||
{t("exploreIsUnavailable.downloadingModels.error")}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-center text-primary-variant">
|
||||
You may want to reindex the embeddings of your tracked objects
|
||||
once the models are downloaded.
|
||||
{t("exploreIsUnavailable.downloadingModels.tips.context")}
|
||||
</div>
|
||||
<div className="flex items-center text-primary-variant">
|
||||
<Link
|
||||
@ -449,7 +462,9 @@ export default function Explore() {
|
||||
rel="noopener noreferrer"
|
||||
className="inline"
|
||||
>
|
||||
Read the documentation{" "}
|
||||
{t(
|
||||
"exploreIsUnavailable.downloadingModels.tips.documentation",
|
||||
)}{" "}
|
||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user