{options.map(entry => !entry.hr ? (
diff --git a/client/src/common/components/Dropdown/utils/infos.jsx b/client/src/common/components/Dropdown/utils/infos.jsx
index 6b78fac0..aebe30e8 100644
--- a/client/src/common/components/Dropdown/utils/infos.jsx
+++ b/client/src/common/components/Dropdown/utils/infos.jsx
@@ -1,16 +1,13 @@
-export const healthChecksInfo = <>MySpeed verwendet
Healthchecks,
- um dich zu benachrichtigen, wenn dein Internet ausfällt. Um dies zu aktivieren, setze deine Ping URL in das Textfeld
- ein. Mehr dazu
hier>;
+import {PROJECT_URL, PROJECT_WIKI} from "@/index";
+import {Trans} from "react-i18next";
+const HEALTHCHECKS_URL = "https://healthchecks.io/";
+const CLI_URL = "https://www.speedtest.net/apps/cli";
-export const creditsInfo = <>
MySpeed wird von GNMYT bereitgestellt und verwendet die
Speedtest-CLI von Ookla.>;
+export const healthChecksInfo = () =>
,
+ WIKILink:
}}>info.healthchecks
-export const recommendationsError = <>Du musst mindestens 10 Tests machen, damit ein Durchschnitt ermittelt werden kann.
- Ob die Tests manuell oder automatisch durchgeführt wurden ist egal.>;
+export const creditsInfo = () =>
,
+ CLILink:
}}>info.credits
-export const recommendationsInfo = (ping, download, upload) => <>Anhand der letzten 10 Testergebnisse wurde
- festgestellt, dass der optimale Ping bei
{ping} ms, der Download bei
{download} Mbit/s und der Upload bei
{upload} Mbit/s liegt.
Orientiere dich am besten an deinem Internetvertrag
- und übernehme es nur, wenn es mit dem übereinstimmt.>;
\ No newline at end of file
+export const recommendationsInfo = (ping, down, up) =>
}}
+ values={{ping, down, up}}>info.recommendations_info
\ No newline at end of file
diff --git a/client/src/common/components/Dropdown/utils/options.js b/client/src/common/components/Dropdown/utils/options.js
index 9159a3ea..32d9299d 100644
--- a/client/src/common/components/Dropdown/utils/options.js
+++ b/client/src/common/components/Dropdown/utils/options.js
@@ -1,19 +1,26 @@
-export const timeOptions = {
- 1: "24 Stunden (Standard)",
- 2: "2 Tage (Insgesamt)",
- 3: "7 Tage (Durchschnitt)",
- 4: "30 Tage (Durchschnitt)"
-};
+import {t} from "i18next";
-export const selectOptions = {
- "* * * * *": "Durchgehend (jede Minute)",
- "0,30 * * * *": "Sehr häufig (alle 30 Minuten)",
- "0 * * * *": "Standard (jede Stunde)",
- "0 0,3,6,9,12,15,18,21 * * *": "Selten (alle 3 Stunden)",
- "0 0,6,12,18 * * *": "Sehr selten (alle 6 Stunden)"
+export const timeOptions = () => ({
+ 1: t("options.time.24hours"),
+ 2: t("options.time.2days"),
+ 3: t("options.time.7days"),
+ 4: t("options.time.30days")
+});
+
+export const selectOptions = () => ({
+ "* * * * *": t("options.cron.continuous"),
+ "0,30 * * * *": t("options.cron.frequent"),
+ "0 * * * *": t("options.cron.default"),
+ "0 0,3,6,9,12,15,18,21 * * *": t("options.cron.rare"),
+ "0 0,6,12,18 * * *": t("options.cron.really_rare")
+});
+
+export const languageOptions = {
+ "en": "English",
+ "de": "Deutsch"
}
-export const exportOptions = {
- json: "JSON-Datei",
- csv: "CSV-Datei"
-}
\ No newline at end of file
+export const exportOptions = () => ({
+ json: t("options.export.json"),
+ csv: t("options.export.csv")
+});
\ No newline at end of file
diff --git a/client/src/common/components/Dropdown/utils/utils.jsx b/client/src/common/components/Dropdown/utils/utils.jsx
index 88696e16..1432db75 100644
--- a/client/src/common/components/Dropdown/utils/utils.jsx
+++ b/client/src/common/components/Dropdown/utils/utils.jsx
@@ -1,11 +1,12 @@
import {parseExpression} from "cron-parser";
+import {t} from "i18next";
// Parses cron as a locale string
export const parseCron = (cron) => {
try {
return parseExpression(cron).next().toDate().toLocaleString()
} catch (e) {
- return
Eingabe ungültig;
+ return
{t("dropdown.invalid")};
}
}
diff --git a/client/src/common/components/Header/HeaderComponent.jsx b/client/src/common/components/Header/HeaderComponent.jsx
index 0feb9717..b81f3f20 100644
--- a/client/src/common/components/Header/HeaderComponent.jsx
+++ b/client/src/common/components/Header/HeaderComponent.jsx
@@ -8,6 +8,7 @@ import {StatusContext} from "@/common/contexts/Status";
import {SpeedtestContext} from "@/common/contexts/Speedtests";
import {jsonRequest, postRequest} from "@/common/utils/RequestUtil";
import {updateInfo} from "@/common/components/Header/utils/infos";
+import {t} from "i18next";
function HeaderComponent() {
const [setDialog] = useContext(DialogContext);
@@ -23,15 +24,15 @@ function HeaderComponent() {
const startSpeedtest = async () => {
await updateStatus();
if (status.paused) return setDialog({
- title: "Fehlgeschlagen",
- description: "Speedtests sind aktuell pausiert. Bitte setze sie fort, wenn du einen machen möchtest.",
- buttonText: "Okay"
+ title: t("failed"),
+ description: t("header.paused"),
+ buttonText: t("dialog.okay")
});
if (status.running) return setDialog({
- title: "Fehlgeschlagen",
- description: "Es läuft bereits ein Speedtest. Bitte gedulde dich ein wenig, bis dieser fertig ist.",
- buttonText: "Okay"
+ title: t("failed"),
+ description: t("header.running"),
+ buttonText: t("dialog.okay")
});
setDialog({speedtest: true, disableCloseButton: true});
@@ -53,13 +54,13 @@ function HeaderComponent() {
return (
-
Netzwerkanalyse
+
{t("header.title")}
{updateAvailable ?
setDialog({
- title: "Update verfügbar",
- buttonText: "Okay",
+ title: t("header.new_update"),
+ buttonText: t("dialog.okay"),
description: updateInfo(updateAvailable)
})}/>
: <>>}
@@ -67,13 +68,13 @@ function HeaderComponent() {
- {status.running ? "Speedtest läuft" : "Speedtest starten"}
+ {t("header." + (status.running ? "running_tooltip" : "start_tooltip"))}
: <>>}
diff --git a/client/src/common/components/Header/utils/infos.jsx b/client/src/common/components/Header/utils/infos.jsx
index 01a09d8b..e3abe85c 100644
--- a/client/src/common/components/Header/utils/infos.jsx
+++ b/client/src/common/components/Header/utils/infos.jsx
@@ -1,5 +1,5 @@
-export const updateInfo = (update) => <>Ein Update auf die Version {update} ist verfügbar. Sieh dir
die
- Änderungen an und
lade dir das
- Update herunter.>;
\ No newline at end of file
+import {Trans} from "react-i18next";
+import {PROJECT_URL, PROJECT_WIKI} from "@/index";
+
+export const updateInfo = (version) =>
,
+ DLLink:
}}>info.update
\ No newline at end of file
diff --git a/client/src/common/contexts/Config/ConfigContext.jsx b/client/src/common/contexts/Config/ConfigContext.jsx
index 543d63aa..440415da 100644
--- a/client/src/common/contexts/Config/ConfigContext.jsx
+++ b/client/src/common/contexts/Config/ConfigContext.jsx
@@ -16,12 +16,12 @@ export const ConfigProvider = (props) => {
return res.json();
})
.then(result => setConfig(result))
- .catch(() => setDialog(passwordRequiredDialog));
+ .catch(() => setDialog(passwordRequiredDialog()));
}
useEffect(() => {
if (config.acceptOoklaLicense !== undefined && config.acceptOoklaLicense === "false")
- setDialog(acceptDialog);
+ setDialog(acceptDialog());
}, [config]);
useEffect(reloadConfig, []);
diff --git a/client/src/common/contexts/Config/dialog.jsx b/client/src/common/contexts/Config/dialog.jsx
index d17f0c69..a6934b39 100644
--- a/client/src/common/contexts/Config/dialog.jsx
+++ b/client/src/common/contexts/Config/dialog.jsx
@@ -1,31 +1,30 @@
import {patchRequest} from "@/common/utils/RequestUtil";
+import {t} from "i18next";
+import {Trans} from "react-i18next";
const OOKLA_ABOUT_URL = "https://www.speedtest.net/about";
const OOKLA_TERMS_URL = OOKLA_ABOUT_URL + "/terms";
const OOKLA_EULA_URL = OOKLA_ABOUT_URL + "/eula";
const OOKLA_PRIVACY_URL = OOKLA_ABOUT_URL + "/privacy";
-export const passwordRequiredDialog = {
- title: "Passwort erforderlich",
- placeholder: "Dein Passwort",
- description: localStorage.getItem("password") ?
-
Das von dir eingegebene Passwort ist falsch : "",
+export const passwordRequiredDialog = () => ({
+ title: t("dialog.password.title"),
+ placeholder: t("dialog.password.placeholder"),
+ description: localStorage.getItem("password") ?
{t("dialog.password.wrong")} : "",
type: "password",
- buttonText: "Fertig",
+ buttonText: t("dialog.done"),
disableCloseButton: true,
onSuccess: (value) => {
localStorage.setItem("password", value);
window.location.reload();
}
-}
+});
-export const acceptDialog = {
- title: "Nutzungsbedingungen akzeptieren",
- description: <>Mit dem Klick auf
Akzeptieren bestätigst du, dass du die
EULA,
Datenschutzerklärung und
Nutzungsbedingungen von Ookla gelesen hast und diesen zustimmst.>,
- buttonText: "Akzeptieren",
+export const acceptDialog = () => ({
+ title: t("dialog.accept.title"),
+ description:
, EULA:
,
+ Privacy:
, Terms:
}}>dialog.accept.description,
+ buttonText: t("dialog.accept.button"),
disableCloseButton: true,
onSuccess: () => patchRequest("/config/acceptOoklaLicense", {value: true})
-}
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/client/src/common/contexts/Dialog/DialogContext.jsx b/client/src/common/contexts/Dialog/DialogContext.jsx
index c209466a..dfafd5f8 100644
--- a/client/src/common/contexts/Dialog/DialogContext.jsx
+++ b/client/src/common/contexts/Dialog/DialogContext.jsx
@@ -2,6 +2,7 @@ import React, {useState, createContext, useEffect, useRef} from "react";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faClose} from "@fortawesome/free-solid-svg-icons";
import "./styles.sass";
+import {t} from "i18next";
export const DialogContext = createContext({});
@@ -71,8 +72,8 @@ const Dialog = ({dialog, setDialog}) => {