I18N Miscellaneous Fixes (#21573)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

* fix: fix classification none tag i18n wrong

* fix: fix set password dialog jwt time i18n wrong

* fix: fix wizard other camera i18n

* fix: fix explore tracking detail audio i18n

* feat: add system processes info i18n

* fix: fix live page label i18n
This commit is contained in:
GuoQing Liu 2026-01-09 05:28:18 +08:00 committed by GitHub
parent 74d14cb8ca
commit f3543cfee2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 49 additions and 26 deletions

View File

@ -101,7 +101,8 @@
"show": "Show {{item}}",
"ID": "ID",
"none": "None",
"all": "All"
"all": "All",
"other": "Other"
},
"list": {
"two": "{{0}} and {{1}}",

View File

@ -86,7 +86,14 @@
"otherProcesses": {
"title": "Other Processes",
"processCpuUsage": "Process CPU Usage",
"processMemoryUsage": "Process Memory Usage"
"processMemoryUsage": "Process Memory Usage",
"series": {
"go2rtc": "go2rtc",
"recording": "recording",
"review_segment": "review segment",
"embeddings": "embeddings",
"audio_detector": "audio detector"
}
}
},
"storage": {

View File

@ -166,7 +166,7 @@ export const ClassificationCard = forwardRef<
<div className="break-all smart-capitalize">
{data.name == "unknown"
? t("details.unknown")
: data.name == "none"
: data.name.toLowerCase() == "none"
? t("details.none")
: data.name}
</div>

View File

@ -22,6 +22,7 @@ import { useTranslation } from "react-i18next";
import { useDocDomain } from "@/hooks/use-doc-domain";
import useSWR from "swr";
import { formatSecondsToDuration } from "@/utils/dateUtil";
import { useDateLocale } from "@/hooks/use-date-locale";
import ActivityIndicator from "../indicators/activity-indicator";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
@ -48,12 +49,13 @@ export default function SetPasswordDialog({
const { t } = useTranslation(["views/settings", "common"]);
const { getLocaleDocUrl } = useDocDomain();
const isAdmin = useIsAdmin();
const dateLocale = useDateLocale();
const { data: config } = useSWR("config");
const refreshSeconds: number | undefined =
config?.auth?.refresh_time ?? undefined;
const refreshTimeLabel = refreshSeconds
? formatSecondsToDuration(refreshSeconds)
? formatSecondsToDuration(refreshSeconds, dateLocale)
: t("time.30minutes", { ns: "common" });
// visibility toggles for password fields

View File

@ -266,7 +266,7 @@ export function TrackingDetails({
const label = event.sub_label
? event.sub_label
: getTranslatedLabel(event.label);
: getTranslatedLabel(event.label, event.data.type);
const getZoneColor = useCallback(
(zoneName: string) => {
@ -998,7 +998,7 @@ function LifecycleIconRow({
<div className="ml-3 flex-shrink-0 px-1 text-right text-xs text-primary-variant">
<div className="flex flex-row items-center gap-3">
<div className="whitespace-nowrap">{formattedEventTimestamp}</div>
{((isAdmin && config?.plus?.enabled) || item.data.box) && (
{isAdmin && config?.plus?.enabled && item.data.box && (
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
<DropdownMenuTrigger>
<div className="rounded p-1 pr-2" role="button">

View File

@ -16,7 +16,6 @@ import {
} from "@/types/live";
import { getIconForLabel } from "@/utils/iconUtil";
import Chip from "../indicators/Chip";
import { capitalizeFirstLetter } from "@/utils/stringUtil";
import { cn } from "@/lib/utils";
import { TbExclamationCircle } from "react-icons/tb";
import { TooltipPortal } from "@radix-ui/react-tooltip";
@ -26,6 +25,8 @@ import { LuVideoOff } from "react-icons/lu";
import { Trans, useTranslation } from "react-i18next";
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay";
import { getTranslatedLabel } from "@/utils/i18n";
import { formatList } from "@/utils/stringUtil";
type LivePlayerProps = {
cameraRef?: (ref: HTMLDivElement | null) => void;
@ -367,20 +368,22 @@ export default function LivePlayer({
</div>
<TooltipPortal>
<TooltipContent className="smart-capitalize">
{[
...new Set([
...(objects || []).map(({ label, sub_label }) =>
label.endsWith("verified")
? sub_label
: label.replaceAll("_", " "),
),
]),
]
.filter((label) => label?.includes("-verified") == false)
.map((label) => capitalizeFirstLetter(label))
.sort()
.join(", ")
.replaceAll("-verified", "")}
{formatList(
[
...new Set([
...(objects || []).map(({ label, sub_label }) =>
label.endsWith("verified")
? sub_label
: label.replaceAll("_", " "),
),
]),
]
.filter((label) => label?.includes("-verified") == false)
.map((label) =>
getTranslatedLabel(label.replace("-verified", "")),
)
.sort(),
)}
</TooltipContent>
</TooltipPortal>
</Tooltip>

View File

@ -417,7 +417,9 @@ export default function Step1NameCamera({
<SelectContent>
{CAMERA_BRANDS.map((brand) => (
<SelectItem key={brand.value} value={brand.value}>
{brand.label}
{brand.label.toLowerCase() === "other"
? t("label.other", { ns: "common" })
: brand.label}
</SelectItem>
))}
</SelectContent>

View File

@ -1,5 +1,5 @@
import { fromUnixTime, intervalToDuration, formatDuration } from "date-fns";
import { Locale } from "date-fns/locale";
import { enUS, Locale } from "date-fns/locale";
import { formatInTimeZone } from "date-fns-tz";
import i18n from "@/utils/i18n";
export const longToDate = (long: number): Date => new Date(long * 1000);
@ -293,9 +293,13 @@ export const getDurationFromTimestamps = (
/**
*
* @param seconds - number of seconds to convert into hours, minutes and seconds
* @param locale - the date-fns locale to use for formatting
* @returns string - formatted duration in hours, minutes and seconds
*/
export const formatSecondsToDuration = (seconds: number): string => {
export const formatSecondsToDuration = (
seconds: number,
locale?: Locale,
): string => {
if (isNaN(seconds) || seconds < 0) {
return "Invalid duration";
}
@ -304,6 +308,7 @@ export const formatSecondsToDuration = (seconds: number): string => {
return formatDuration(duration, {
format: ["hours", "minutes", "seconds"],
delimiter: ", ",
locale: locale ?? enUS,
});
};

View File

@ -12,7 +12,10 @@ export function getLifecycleItemDescription(
const label = lifecycleItem.data.sub_label
? capitalizeFirstLetter(rawLabel)
: getTranslatedLabel(rawLabel);
: getTranslatedLabel(
rawLabel,
lifecycleItem.class_type === "heard" ? "audio" : "object",
);
switch (lifecycleItem.class_type) {
case "visible":

View File

@ -855,7 +855,7 @@ export default function GeneralMetrics({
<ThresholdBarGraph
key={series.name}
graphId={`${series.name}-cpu`}
name={series.name.replaceAll("_", " ")}
name={t(`general.otherProcesses.series.${series.name}`)}
unit="%"
threshold={DetectorCpuThreshold}
updateTimes={updateTimes}