fix: fix i18n (#23174)
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 embedding time locale

* fix: fix setting i18n

* fix: fix lpr setting item i18n

* fix: fix code
This commit is contained in:
GuoQing Liu 2026-05-13 20:38:33 +08:00 committed by GitHub
parent f1e2240945
commit 19ec6fa245
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 89 additions and 21 deletions

View File

@ -1659,12 +1659,17 @@
"continuous": "Continuous" "continuous": "Continuous"
} }
}, },
"snapshot": { "retainMode": {
"retainMode": { "all": "All",
"all": "All", "motion": "Motion",
"motion": "Motion", "active_objects": "Active Objects"
"active_objects": "Active Objects" },
} "previewQuality": {
"very_high": "Very High",
"high": "High",
"medium": "Medium",
"low": "Low",
"very_low": "Very Low"
}, },
"ui": { "ui": {
"timeFormat": { "timeFormat": {
@ -1700,7 +1705,14 @@
}, },
"onvif": { "onvif": {
"profileAuto": "Auto", "profileAuto": "Auto",
"profileLoading": "Loading profiles..." "profileLoading": "Loading profiles...",
"autotracking": {
"zooming": {
"disabled": "Disabled",
"absolute": "Absolute",
"relative": "Relative"
}
}
}, },
"modelSize": { "modelSize": {
"small": "Small", "small": "Small",

View File

@ -42,6 +42,7 @@ const audio: SectionConfigOverrides = {
"filters.*": { "filters.*": {
"ui:options": { "ui:options": {
additionalPropertyKeyReadonly: true, additionalPropertyKeyReadonly: true,
isAudioLabels: true,
}, },
}, },
listen: { listen: {

View File

@ -25,6 +25,11 @@ const audioTranscription: SectionConfigOverrides = {
hiddenFields: ["enabled_in_config", "live_enabled"], hiddenFields: ["enabled_in_config", "live_enabled"],
advancedFields: ["language", "device", "model_size"], advancedFields: ["language", "device", "model_size"],
overrideFields: ["enabled", "live_enabled"], overrideFields: ["enabled", "live_enabled"],
uiSchema: {
model_size: {
"ui:options": { size: "xs", enumI18nPrefix: "modelSize" },
},
},
}, },
global: { global: {
fieldOrder: ["enabled", "language", "device", "model_size"], fieldOrder: ["enabled", "language", "device", "model_size"],

View File

@ -65,7 +65,7 @@ const faceRecognition: SectionConfigOverrides = {
], ],
uiSchema: { uiSchema: {
model_size: { model_size: {
"ui:options": { size: "xs" }, "ui:options": { size: "xs", enumI18nPrefix: "modelSize" },
}, },
}, },
}, },

View File

@ -39,6 +39,11 @@ const onvif: SectionConfigOverrides = {
track: { track: {
"ui:widget": "objectLabels", "ui:widget": "objectLabels",
}, },
zooming: {
"ui:options": {
enumI18nPrefix: "onvif.autotracking.zooming",
},
},
}, },
}, },
}, },

View File

@ -49,6 +49,17 @@ const record: SectionConfigOverrides = {
"ui:options": { suppressMultiSchema: true, size: "lg" }, "ui:options": { suppressMultiSchema: true, size: "lg" },
}, },
}, },
"alerts.retain.mode": {
"ui:options": { enumI18nPrefix: "retainMode" },
},
"detections.retain.mode": {
"ui:options": { enumI18nPrefix: "retainMode" },
},
"preview.quality": {
"ui:options": {
enumI18nPrefix: "previewQuality",
},
},
}, },
}, },
global: { global: {

View File

@ -37,7 +37,7 @@ const snapshots: SectionConfigOverrides = {
}, },
"retain.mode": { "retain.mode": {
"ui:options": { "ui:options": {
enumI18nPrefix: "snapshot.retainMode", enumI18nPrefix: "retainMode",
}, },
}, },
}, },

View File

@ -28,7 +28,11 @@ export function KnownPlatesField(props: FieldProps) {
| ConfigFormContext | ConfigFormContext
| undefined; | undefined;
const { t } = useTranslation(["views/settings", "common"]); const configNamespace =
formContext?.i18nNamespace ??
(formContext?.level === "camera" ? "config/cameras" : "config/global");
const { t: fallbackT } = useTranslation(["common", configNamespace]);
const t = formContext?.t ?? fallbackT;
const data: KnownPlatesData = useMemo(() => { const data: KnownPlatesData = useMemo(() => {
if (!formData || typeof formData !== "object" || Array.isArray(formData)) { if (!formData || typeof formData !== "object" || Array.isArray(formData)) {
@ -39,8 +43,14 @@ export function KnownPlatesField(props: FieldProps) {
const entries = useMemo(() => Object.entries(data), [data]); const entries = useMemo(() => Object.entries(data), [data]);
const title = (schema as RJSFSchema).title; const id = idSchema?.$id ?? props.name;
const description = (schema as RJSFSchema).description; const sectionPrefix = formContext?.sectionI18nPrefix;
const title =
t(`${sectionPrefix}.${id}.label`) ?? (schema as RJSFSchema).title;
const description =
t(`${sectionPrefix}.${id}.description`) ??
(schema as RJSFSchema).description;
const hasItems = entries.length > 0; const hasItems = entries.length > 0;
const emptyPath = useMemo(() => [] as FieldPathList, []); const emptyPath = useMemo(() => [] as FieldPathList, []);

View File

@ -47,7 +47,11 @@ export function ReplaceRulesField(props: FieldProps) {
| ConfigFormContext | ConfigFormContext
| undefined; | undefined;
const { t } = useTranslation(["common"]); const configNamespace =
formContext?.i18nNamespace ??
(formContext?.level === "camera" ? "config/cameras" : "config/global");
const { t: fallbackT } = useTranslation(["common", configNamespace]);
const t = formContext?.t ?? fallbackT;
const rules: ReplaceRule[] = useMemo(() => { const rules: ReplaceRule[] = useMemo(() => {
if (!Array.isArray(formData)) { if (!Array.isArray(formData)) {
@ -60,10 +64,21 @@ export function ReplaceRulesField(props: FieldProps) {
() => getItemSchema(schema as RJSFSchema), () => getItemSchema(schema as RJSFSchema),
[schema], [schema],
); );
const title = (schema as RJSFSchema).title;
const description = (schema as RJSFSchema).description; const id = idSchema?.$id ?? props.name;
const patternTitle = getPropertyTitle(itemSchema, "pattern"); const sectionPrefix = formContext?.sectionI18nPrefix;
const replacementTitle = getPropertyTitle(itemSchema, "replacement");
const title =
t(`${sectionPrefix}.${id}.label`) ?? (schema as RJSFSchema).title;
const description =
t(`${sectionPrefix}.${id}.description`) ??
(schema as RJSFSchema).description;
const patternTitle =
t(`${sectionPrefix}.${id}.pattern.label`) ??
getPropertyTitle(itemSchema, "pattern");
const replacementTitle =
t(`${sectionPrefix}.${id}.replacement.label`) ??
getPropertyTitle(itemSchema, "replacement");
const hasItems = rules.length > 0; const hasItems = rules.length > 0;
const emptyPath = useMemo(() => [] as FieldPathList, []); const emptyPath = useMemo(() => [] as FieldPathList, []);

View File

@ -210,6 +210,9 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) {
(p.content.props as RjsfElementProps).uiSchema?.["ui:options"] (p.content.props as RjsfElementProps).uiSchema?.["ui:options"]
?.advanced !== true, ?.advanced !== true,
); );
const isAudioLabels = uiSchema?.["ui:options"]?.isAudioLabels === true;
const hasModifiedAdvanced = advancedProps.some((prop) => const hasModifiedAdvanced = advancedProps.some((prop) =>
checkSubtreeModified([...fieldPath, prop.name]), checkSubtreeModified([...fieldPath, prop.name]),
); );
@ -243,7 +246,7 @@ export function ObjectFieldTemplate(props: ObjectFieldTemplateProps) {
const path = fieldPathId?.path; const path = fieldPathId?.path;
const filterObjectLabel = path ? getFilterObjectLabel(path) : undefined; const filterObjectLabel = path ? getFilterObjectLabel(path) : undefined;
const translatedFilterLabel = filterObjectLabel const translatedFilterLabel = filterObjectLabel
? getTranslatedLabel(filterObjectLabel, "object") ? getTranslatedLabel(filterObjectLabel, isAudioLabels ? "audio" : "object")
: undefined; : undefined;
if (path) { if (path) {
translationPath = buildTranslationPath( translationPath = buildTranslationPath(

View File

@ -24,6 +24,7 @@ import useSWR from "swr";
import useSWRInfinite from "swr/infinite"; import useSWRInfinite from "swr/infinite";
import { useDocDomain } from "@/hooks/use-doc-domain"; import { useDocDomain } from "@/hooks/use-doc-domain";
import { JINA_EMBEDDING_MODELS } from "@/lib/const"; import { JINA_EMBEDDING_MODELS } from "@/lib/const";
import { useDateLocale } from "@/hooks/use-date-locale";
const API_LIMIT = 25; const API_LIMIT = 25;
@ -43,6 +44,8 @@ export default function Explore() {
const { t } = useTranslation(["views/explore"]); const { t } = useTranslation(["views/explore"]);
const { getLocaleDocUrl } = useDocDomain(); const { getLocaleDocUrl } = useDocDomain();
const dateLocale = useDateLocale();
const { data: config } = useSWR<FrigateConfig>("config", { const { data: config } = useSWR<FrigateConfig>("config", {
revalidateOnFocus: false, revalidateOnFocus: false,
}); });
@ -417,7 +420,10 @@ export default function Explore() {
)} )}
</div> </div>
{reindexState.time_remaining >= 0 && {reindexState.time_remaining >= 0 &&
(formatSecondsToDuration(reindexState.time_remaining) || (formatSecondsToDuration(
reindexState.time_remaining,
dateLocale,
) ||
t( t(
"exploreIsUnavailable.embeddingsReindexing.finishingShortly", "exploreIsUnavailable.embeddingsReindexing.finishingShortly",
))} ))}