mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-02 09:02:15 +03:00
feat: add i18n (translation/localization) (#16877)
* Translation module init * Add more i18n keys * fix: fix string wrong * refactor: use namespace translation file * chore: add more translation key * fix: fix some page name error * refactor: change Trans tag for t function * chore: fix some key not work * chore: fix SearchFilterDialog i18n key error Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * chore: fix en i18n file filter missing some keys * chore: add some i18n keys * chore: add more i18n keys again * feat: add search page i18n * feat: add explore model i18n keys * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * feat: add more live i18n keys * feat: add more search setting i18n keys * fix: remove some comment * fix: fix some setting page url error * Update web/src/views/settings/SearchSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * fix: add system missing keys * fix: update password update i18n keys * chore: remove outdate translation.json file * fix: fix exploreSettings error * chore: add object setting i18n keys * Update web/src/views/recording/RecordingView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/public/locales/en/components/filter.json Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/overlay/ExportDialog.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * feat: add more i18n keys * fix: fix motionDetectionTuner html node * feat: add more page i18n keys * fix: cameraStream i18n keys error * feat: add Player i18n keys * feat: add more toast i18n keys * feat: change explore setting name * feat: add more document title i18n keys * feat: add more search i18n keys * fix: fix accessDenied i18n keys error * chore: add objectType i18n * chore: add inputWithTags i18n * chore: add SearchFilterDialog i18n * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * chore: add some missing i18n keys * chore: remove most import { t } from "i18next"; --------- Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
This commit is contained in:
co-authored by
Josh Hawkins
parent
db541abed4
commit
d34533981f
@@ -15,6 +15,7 @@ import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
import { Toaster } from "../ui/sonner";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
type CameraInfoDialogProps = {
|
||||
camera: CameraConfig;
|
||||
@@ -26,6 +27,7 @@ export default function CameraInfoDialog({
|
||||
showCameraInfoDialog,
|
||||
setShowCameraInfoDialog,
|
||||
}: CameraInfoDialogProps) {
|
||||
const { t } = useTranslation(["views/system"]);
|
||||
const [ffprobeInfo, setFfprobeInfo] = useState<Ffprobe[]>();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -39,15 +41,25 @@ export default function CameraInfoDialog({
|
||||
if (res.status === 200) {
|
||||
setFfprobeInfo(res.data);
|
||||
} else {
|
||||
toast.error(`Unable to probe camera: ${res.statusText}`, {
|
||||
position: "top-center",
|
||||
});
|
||||
toast.error(
|
||||
t("cameras.toast.success.copyToClipboard", {
|
||||
errorMessage: res.statusText,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(`Unable to probe camera: ${error.response.data.message}`, {
|
||||
position: "top-center",
|
||||
});
|
||||
toast.error(
|
||||
t("cameras.toast.success.copyToClipboard", {
|
||||
errorMessage: error.response.data.message,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
});
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -55,7 +67,7 @@ export default function CameraInfoDialog({
|
||||
|
||||
const onCopyFfprobe = async () => {
|
||||
copy(JSON.stringify(ffprobeInfo));
|
||||
toast.success("Copied probe data to clipboard.");
|
||||
toast.success(t("cameras.toast.success.copyToClipboard"));
|
||||
};
|
||||
|
||||
function gcd(a: number, b: number): number {
|
||||
@@ -72,11 +84,13 @@ export default function CameraInfoDialog({
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="capitalize">
|
||||
{camera.name.replaceAll("_", " ")} Camera Probe Info
|
||||
{t("cameras.info.cameraProbeInfo", {
|
||||
camera: camera.name.replaceAll("_", " "),
|
||||
})}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
Stream data is obtained with <code>ffprobe</code>.
|
||||
<Trans ns="views/system">cameras.info.streamDataFromFFPROBE</Trans>
|
||||
</DialogDescription>
|
||||
|
||||
<div className="mb-2 p-4">
|
||||
@@ -85,7 +99,9 @@ export default function CameraInfoDialog({
|
||||
{ffprobeInfo.map((stream, idx) => (
|
||||
<div key={idx} className="mb-5">
|
||||
<div className="mb-1 rounded-md bg-secondary p-2 text-lg text-primary">
|
||||
Stream {idx + 1}
|
||||
{t("cameras.info.stream", {
|
||||
idx: idx + 1,
|
||||
})}
|
||||
</div>
|
||||
{stream.return_code == 0 ? (
|
||||
<div>
|
||||
@@ -93,10 +109,12 @@ export default function CameraInfoDialog({
|
||||
<div className="" key={idx}>
|
||||
{codec.width ? (
|
||||
<div className="text-muted-foreground">
|
||||
<div className="ml-2">Video:</div>
|
||||
<div className="ml-2">
|
||||
{t("cameras.info.video")}
|
||||
</div>
|
||||
<div className="ml-5">
|
||||
<div>
|
||||
Codec:
|
||||
{t("cameras.info.codec")}
|
||||
<span className="text-primary">
|
||||
{" "}
|
||||
{codec.codec_long_name}
|
||||
@@ -105,7 +123,7 @@ export default function CameraInfoDialog({
|
||||
<div>
|
||||
{codec.width && codec.height ? (
|
||||
<>
|
||||
Resolution:{" "}
|
||||
{t("cameras.info.resolution")}{" "}
|
||||
<span className="text-primary">
|
||||
{" "}
|
||||
{codec.width}x{codec.height} (
|
||||
@@ -119,7 +137,7 @@ export default function CameraInfoDialog({
|
||||
</>
|
||||
) : (
|
||||
<span>
|
||||
Resolution:{" "}
|
||||
{t("cameras.info.resolution")}{" "}
|
||||
<span className="text-primary">
|
||||
Unknown
|
||||
</span>
|
||||
@@ -127,10 +145,10 @@ export default function CameraInfoDialog({
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
FPS:{" "}
|
||||
{t("cameras.info.fps")}{" "}
|
||||
<span className="text-primary">
|
||||
{codec.avg_frame_rate == "0/0"
|
||||
? "Unknown"
|
||||
? t("cameras.info.unknown")
|
||||
: codec.avg_frame_rate}
|
||||
</span>
|
||||
</div>
|
||||
@@ -140,7 +158,7 @@ export default function CameraInfoDialog({
|
||||
<div className="text-muted-foreground">
|
||||
<div className="ml-2 mt-1">Audio:</div>
|
||||
<div className="ml-4">
|
||||
Codec:{" "}
|
||||
{t("cameras.info.codec")}{" "}
|
||||
<span className="text-primary">
|
||||
{codec.codec_long_name}
|
||||
</span>
|
||||
@@ -152,7 +170,11 @@ export default function CameraInfoDialog({
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-2">
|
||||
<div>Error: {stream.stderr}</div>
|
||||
<div>
|
||||
{t("cameras.info.error", {
|
||||
error: stream.stderr,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -161,7 +183,7 @@ export default function CameraInfoDialog({
|
||||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<ActivityIndicator />
|
||||
<div className="mt-2">Fetching Camera Data</div>
|
||||
<div className="mt-2">{t("cameras.info.fetching")}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -169,10 +191,10 @@ export default function CameraInfoDialog({
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="select"
|
||||
aria-label="Copy"
|
||||
aria-label={t("button.copy", { ns: "common" })}
|
||||
onClick={() => onCopyFfprobe()}
|
||||
>
|
||||
Copy
|
||||
{t("button.copy", { ns: "common" })}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
Reference in New Issue
Block a user