diff --git a/interface/src/SignIn.tsx b/interface/src/SignIn.tsx index 8ba119137..dc67ad09c 100644 --- a/interface/src/SignIn.tsx +++ b/interface/src/SignIn.tsx @@ -105,7 +105,7 @@ const SignIn: FC = () => { > ({ maxWidth: '250px', whiteSpace: 'nowrap', @@ -23,6 +40,15 @@ const LayoutAuthMenu: FC = () => { setAnchorEl(event.currentTarget); }; + const { locale, LL, setLocale } = useContext(I18nContext); + + const onLocaleSelected: ChangeEventHandler = async ({ target }) => { + const loc = target.value as Locales; + localStorage.setItem('lang', loc); + await loadLocaleAsync(loc); + setLocale(loc); + }; + const handleClose = () => { setAnchorEl(null); }; @@ -32,7 +58,20 @@ const LayoutAuthMenu: FC = () => { return ( <> - + + {locales.map((loc) => ( + + {loc} + + ))} + + { diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 0efd7ef8b..fac0ab414 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -4,6 +4,7 @@ const de: Translation = { LANGUAGE: 'Sprache', IS_REQUIRED: 'ist nötig', SIGN_IN: 'Einloggen', + SIGN_OUT: 'Ausloggen', USERNAME: 'Nutzername', PASSWORD: 'Passwort', DASHBOARD: 'Armaturenbrett', @@ -38,12 +39,36 @@ const de: Translation = { REMOVE: 'Entfernen', PROBLEM_UPDATING: 'Problem beim Aktualisieren', ACCESS_DENIED: 'Zugriff abgelehnt', - ANALOG_SENSOR: 'Analoger Sensor {cmd}', - TEMP_SENSOR: 'Temperatursensor {cmd}', + ANALOG_SENSOR: 'Analoger Sensor{post}', + TEMP_SENSOR: 'Temperatursensor{post}', WRITE_COMMAND: 'Befehl schreiben {cmd}', EMS_BUS_WARNING: 'EMS-Bus getrennt. Wenn diese Warnung nach einigen Sekunden immer noch besteht, überprüfen Sie bitte die Einstellungen und das Board-Profil', - EMS_BUS_SCANNING: 'Scannen nach EMS devices...' + EMS_BUS_SCANNING: 'Scannen nach EMS devices...', + CONNECTED: 'in Verbindung gebracht', + TX_ISSUES: 'Tx-Probleme - versuchen Sie einen anderen Tx-Modus', + DISCONNECTED: 'Getrennt', + SCANNING: 'Suche nach Geräten...', + EMS_SCAN: 'Möchten Sie wirklich einen vollständigen Gerätescan des EMS-Busses starten?', + EMS_BUS_STATUS: 'EMS Bus Status', + ACTIVE_DEVICES: 'Aktive Geräte und Sensoren', + DEVICE: 'Device', + SUCCESS: 'ERFOLG', + FAIL: 'SCHEITERN', + QUALITY: 'QUALITÄT', + SCAN_DEVICES: 'Nach neuen Geräten suchen', + EMS_BUS_STATUS_TITLE: 'EMS Bus und Aktivitätsstatus', + SCAN: 'Scan', + STATUS_NAMES: [ + 'EMS Telegramme erhalten (Rx)', + 'EMS Liest (Tx)', + 'EMS Schreibt (Tx)', + 'Temperatursensor liest', + 'Analoger Sensor liest', + 'MQTT Veröffentlicht', + 'API Aufrufe', + 'Syslog Mitteilungen' + ] }; export default de; diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 5ae97d9fd..fe760415f 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -4,6 +4,7 @@ const en: BaseTranslation = { LANGUAGE: 'Language', IS_REQUIRED: 'is required', SIGN_IN: 'Sign In', + SIGN_OUT: 'Sign Out', USERNAME: 'Username', PASSWORD: 'Password', DASHBOARD: 'Dashboard', @@ -38,12 +39,36 @@ const en: BaseTranslation = { REMOVE: 'Remove', PROBLEM_UPDATING: 'Problem updating', ACCESS_DENIED: 'Access Denied', - ANALOG_SENSOR: 'Analog Sensor {cmd}', - TEMP_SENSOR: 'Temperature Sensor {cmd}', + ANALOG_SENSOR: 'Analog Sensor{post}', + TEMP_SENSOR: 'Temperature Sensor{post}', WRITE_COMMAND: 'Write command {cmd}', EMS_BUS_WARNING: 'EMS bus disconnected. If this warning still persists after a few seconds please check settings and board profile', - EMS_BUS_SCANNING: 'Scanning for EMS devices...' + EMS_BUS_SCANNING: 'Scanning for EMS devices...', + CONNECTED: 'Connected', + TX_ISSUES: 'Tx issues - try a different Tx Mode', + DISCONNECTED: 'Disconnected', + SCANNING: 'Scanning for devices...', + EMS_SCAN: 'Are you sure you want to initiate a full device scan of the EMS bus?', + EMS_BUS_STATUS: 'EMS Bus Status', + ACTIVE_DEVICES: 'Active Devices & Sensors', + DEVICE: 'Device', + SUCCESS: 'SUCCESS', + FAIL: 'FAIL', + QUALITY: 'QUALITY', + SCAN_DEVICES: 'Scan for new devices', + EMS_BUS_STATUS_TITLE: 'EMS Bus & Activity Status', + SCAN: 'Scan', + STATUS_NAMES: [ + 'EMS Telegrams Received (Rx)', + 'EMS Reads (Tx)', + 'EMS Writes (Tx)', + 'Temperature Sensor Reads', + 'Analog Sensor Reads', + 'MQTT Publishes', + 'API Calls', + 'Syslog Messages' + ] }; export default en; diff --git a/interface/src/i18n/i18n-types.ts b/interface/src/i18n/i18n-types.ts index fe7a0f0fb..3e81fc391 100644 --- a/interface/src/i18n/i18n-types.ts +++ b/interface/src/i18n/i18n-types.ts @@ -26,6 +26,10 @@ type RootTranslation = { * Sign In */ SIGN_IN: string + /** + * Sign Out + */ + SIGN_OUT: string /** * Username */ @@ -164,15 +168,15 @@ type RootTranslation = { */ ACCESS_DENIED: string /** - * Analog Sensor {cmd} - * @param {unknown} cmd + * Analog Sensor{post} + * @param {unknown} post */ - ANALOG_SENSOR: RequiredParams<'cmd'> + ANALOG_SENSOR: RequiredParams<'post'> /** - * Temperature Sensor {cmd} - * @param {unknown} cmd + * Temperature Sensor{post} + * @param {unknown} post */ - TEMP_SENSOR: RequiredParams<'cmd'> + TEMP_SENSOR: RequiredParams<'post'> /** * Write command {cmd} * @param {unknown} cmd @@ -186,6 +190,96 @@ type RootTranslation = { * Scanning for EMS devices... */ EMS_BUS_SCANNING: string + /** + * Connected + */ + CONNECTED: string + /** + * Tx issues - try a different Tx Mode + */ + TX_ISSUES: string + /** + * Disconnected + */ + DISCONNECTED: string + /** + * Scanning for devices... + */ + SCANNING: string + /** + * Are you sure you want to initiate a full device scan of the EMS bus? + */ + EMS_SCAN: string + /** + * EMS Bus Status + */ + EMS_BUS_STATUS: string + /** + * Active Devices & Sensors + */ + ACTIVE_DEVICES: string + /** + * Device + */ + DEVICE: string + /** + * SUCCESS + */ + SUCCESS: string + /** + * FAIL + */ + FAIL: string + /** + * QUALITY + */ + QUALITY: string + /** + * Scan for new devices + */ + SCAN_DEVICES: string + /** + * EMS Bus & Activity Status + */ + EMS_BUS_STATUS_TITLE: string + /** + * Scan + */ + SCAN: string + STATUS_NAMES: { + /** + * EMS Telegrams Received (Rx) + */ + '0': string + /** + * EMS Reads (Tx) + */ + '1': string + /** + * EMS Writes (Tx) + */ + '2': string + /** + * Temperature Sensor Reads + */ + '3': string + /** + * Analog Sensor Reads + */ + '4': string + /** + * MQTT Publishes + */ + '5': string + /** + * API Calls + */ + '6': string + /** + * Syslog Messages + */ + '7': string + } } export type TranslationFunctions = { @@ -201,6 +295,10 @@ export type TranslationFunctions = { * Sign In */ SIGN_IN: () => LocalizedString + /** + * Sign Out + */ + SIGN_OUT: () => LocalizedString /** * Username */ @@ -338,13 +436,13 @@ export type TranslationFunctions = { */ ACCESS_DENIED: () => LocalizedString /** - * Analog Sensor {cmd} + * Analog Sensor{post} */ - ANALOG_SENSOR: (arg: { cmd: unknown }) => LocalizedString + ANALOG_SENSOR: (arg: { post: unknown }) => LocalizedString /** - * Temperature Sensor {cmd} + * Temperature Sensor{post} */ - TEMP_SENSOR: (arg: { cmd: unknown }) => LocalizedString + TEMP_SENSOR: (arg: { post: unknown }) => LocalizedString /** * Write command {cmd} */ @@ -357,6 +455,96 @@ export type TranslationFunctions = { * Scanning for EMS devices... */ EMS_BUS_SCANNING: () => LocalizedString + /** + * Connected + */ + CONNECTED: () => LocalizedString + /** + * Tx issues - try a different Tx Mode + */ + TX_ISSUES: () => LocalizedString + /** + * Disconnected + */ + DISCONNECTED: () => LocalizedString + /** + * Scanning for devices... + */ + SCANNING: () => LocalizedString + /** + * Are you sure you want to initiate a full device scan of the EMS bus? + */ + EMS_SCAN: () => LocalizedString + /** + * EMS Bus Status + */ + EMS_BUS_STATUS: () => LocalizedString + /** + * Active Devices & Sensors + */ + ACTIVE_DEVICES: () => LocalizedString + /** + * Device + */ + DEVICE: () => LocalizedString + /** + * SUCCESS + */ + SUCCESS: () => LocalizedString + /** + * FAIL + */ + FAIL: () => LocalizedString + /** + * QUALITY + */ + QUALITY: () => LocalizedString + /** + * Scan for new devices + */ + SCAN_DEVICES: () => LocalizedString + /** + * EMS Bus & Activity Status + */ + EMS_BUS_STATUS_TITLE: () => LocalizedString + /** + * Scan + */ + SCAN: () => LocalizedString + STATUS_NAMES: { + /** + * EMS Telegrams Received (Rx) + */ + '0': () => LocalizedString + /** + * EMS Reads (Tx) + */ + '1': () => LocalizedString + /** + * EMS Writes (Tx) + */ + '2': () => LocalizedString + /** + * Temperature Sensor Reads + */ + '3': () => LocalizedString + /** + * Analog Sensor Reads + */ + '4': () => LocalizedString + /** + * MQTT Publishes + */ + '5': () => LocalizedString + /** + * API Calls + */ + '6': () => LocalizedString + /** + * Syslog Messages + */ + '7': () => LocalizedString + } } export type Formatters = {} diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index e7dff9557..d5b43b3a3 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -530,11 +530,11 @@ const DashboardData: FC = () => { offset: sensor.o }); if (response.status === 204) { - enqueueSnackbar(LL.TEMP_SENSOR({ cmd: 'change failed' }), { variant: 'error' }); + enqueueSnackbar(LL.TEMP_SENSOR({ post: ' change failed' }), { variant: 'error' }); } else if (response.status === 403) { enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); } else { - enqueueSnackbar(LL.TEMP_SENSOR({ cmd: 'removed' }), { variant: 'success' }); + enqueueSnackbar(LL.TEMP_SENSOR({ post: ' removed' }), { variant: 'success' }); } setSensor(undefined); } catch (error: unknown) { @@ -955,11 +955,11 @@ const DashboardData: FC = () => { }); if (response.status === 204) { - enqueueSnackbar(LL.ANALOG_SENSOR({ cmd: 'deletion failed' }), { variant: 'error' }); + enqueueSnackbar(LL.ANALOG_SENSOR({ post: ' deletion failed' }), { variant: 'error' }); } else if (response.status === 403) { enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); } else { - enqueueSnackbar(LL.ANALOG_SENSOR({ cmd: 'removed' }), { variant: 'success' }); + enqueueSnackbar(LL.ANALOG_SENSOR({ post: ' removed' }), { variant: 'success' }); } } catch (error: unknown) { enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); @@ -983,11 +983,11 @@ const DashboardData: FC = () => { }); if (response.status === 204) { - enqueueSnackbar(LL.ANALOG_SENSOR({ cmd: 'update failed' }), { variant: 'error' }); + enqueueSnackbar(LL.ANALOG_SENSOR({ post: ' update failed' }), { variant: 'error' }); } else if (response.status === 403) { enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); } else { - enqueueSnackbar(LL.ANALOG_SENSOR({ cmd: 'updated' }), { variant: 'success' }); + enqueueSnackbar(LL.ANALOG_SENSOR({ post: ' updated' }), { variant: 'success' }); } } catch (error: unknown) { enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index 28783c42d..eadf1bef4 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -36,6 +36,9 @@ import { formatDurationSec, pluralize, extractErrorMessage, useRest } from '../u import * as EMSESP from './api'; +import type { Translation } from '../i18n/i18n-types'; +import { useI18nContext } from '../i18n/i18n-react'; + export const isConnected = ({ status }: Status) => status !== busConnectionStatus.BUS_STATUS_OFFLINE; const busStatusHighlight = ({ status }: Status, theme: Theme) => { @@ -51,19 +54,6 @@ const busStatusHighlight = ({ status }: Status, theme: Theme) => { } }; -const busStatus = ({ status }: Status) => { - switch (status) { - case busConnectionStatus.BUS_STATUS_CONNECTED: - return 'Connected'; - case busConnectionStatus.BUS_STATUS_TX_ERRORS: - return 'Tx issues - try a different Tx Mode'; - case busConnectionStatus.BUS_STATUS_OFFLINE: - return 'Disconnected'; - default: - return 'Unknown'; - } -}; - const showQuality = (stat: Stat) => { if (stat.q === 0 || stat.s + stat.f === 0) { return; @@ -81,12 +71,32 @@ const showQuality = (stat: Stat) => { const DashboardStatus: FC = () => { const { loadData, data, errorMessage } = useRest({ read: EMSESP.readStatus }); + const { LL } = useI18nContext(); + const theme = useTheme(); const [confirmScan, setConfirmScan] = useState(false); const { enqueueSnackbar } = useSnackbar(); const { me } = useContext(AuthenticatedContext); + const showName = (id: any) => { + let name: keyof Translation['STATUS_NAMES'] = id; + return LL.STATUS_NAMES[name](); + }; + + const busStatus = ({ status }: Status) => { + switch (status) { + case busConnectionStatus.BUS_STATUS_CONNECTED: + return LL.CONNECTED(); + case busConnectionStatus.BUS_STATUS_TX_ERRORS: + return LL.TX_ISSUES(); + case busConnectionStatus.BUS_STATUS_OFFLINE: + return LL.DISCONNECTED(); + default: + return 'Unknown'; + } + }; + const stats_theme = tableTheme({ Table: ` --data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 90px 90px 80px; @@ -137,9 +147,9 @@ const DashboardStatus: FC = () => { const scan = async () => { try { await EMSESP.scanDevices(); - enqueueSnackbar('Scanning for devices...', { variant: 'info' }); + enqueueSnackbar(LL.SCANNING(), { variant: 'info' }); } catch (error: unknown) { - enqueueSnackbar(extractErrorMessage(error, 'Problem initiating scan'), { variant: 'error' }); + enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); } finally { setConfirmScan(false); } @@ -147,14 +157,14 @@ const DashboardStatus: FC = () => { const renderScanDialog = () => ( setConfirmScan(false)}> - EMS Device Scan - Are you sure you want to initiate a full device scan of the EMS bus? + {LL.SCAN_DEVICES()} + {LL.EMS_SCAN()} @@ -174,7 +184,7 @@ const DashboardStatus: FC = () => { - + @@ -183,13 +193,13 @@ const DashboardStatus: FC = () => { @@ -200,15 +210,15 @@ const DashboardStatus: FC = () => {
- SUCCESS - FAIL - QUALITY + {LL.SUCCESS()} + {LL.FAIL()} + {LL.QUALITY()}
{tableList.map((stat: Stat) => ( - {stat.id} + {showName(stat.id)} {Intl.NumberFormat().format(stat.s)} {Intl.NumberFormat().format(stat.f)} {showQuality(stat)} @@ -223,7 +233,7 @@ const DashboardStatus: FC = () => { @@ -235,7 +245,7 @@ const DashboardStatus: FC = () => { disabled={!me.admin} onClick={() => setConfirmScan(true)} > - Scan for new devices + {LL.SCAN_DEVICES()} @@ -245,7 +255,7 @@ const DashboardStatus: FC = () => { }; return ( - + {content()} ); diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 7aab6237a..0cd31875f 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -42,7 +42,7 @@ export enum busConnectionStatus { } export interface Stat { - id: string; // name + id: string; // id - needs to be a string s: number; // success f: number; // fail q: number; // quality diff --git a/mock-api/server.js b/mock-api/server.js index 4706b288f..52dd44507 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -425,13 +425,13 @@ const status = { num_sensors: 1, num_analogs: 1, stats: [ - { id: 'EMS Telegrams Received (Rx)', s: 56506, f: 11, q: 100 }, - { id: 'EMS Reads (Tx)', s: 9026, f: 0, q: 100 }, - { id: 'EMS Writes (Tx)', s: 33, f: 2, q: 95 }, - { id: 'Temperature Sensor Reads', s: 56506, f: 11, q: 100 }, - { id: 'Analog Sensor Reads', s: 0, f: 0, q: 100 }, - { id: 'MQTT Publishes', s: 12, f: 10, q: 20 }, - { id: 'API Calls', s: 0, f: 0, q: 0 }, + { id: '0', s: 56506, f: 11, q: 100 }, + { id: '1', s: 9026, f: 0, q: 100 }, + { id: '2', s: 33, f: 2, q: 95 }, + { id: '3', s: 56506, f: 11, q: 100 }, + { id: '4', s: 0, f: 0, q: 100 }, + { id: '5', s: 12, f: 10, q: 20 }, + { id: '6', s: 0, f: 0, q: 0 }, ], } diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 42c91e983..63290f5e4 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -141,47 +141,47 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) { JsonObject statJson; statJson = statsJson.createNestedObject(); - statJson["id"] = "EMS Telegrams Received (Rx)"; + statJson["id"] = "0"; statJson["s"] = EMSESP::rxservice_.telegram_count(); statJson["f"] = EMSESP::rxservice_.telegram_error_count(); statJson["q"] = EMSESP::rxservice_.quality(); statJson = statsJson.createNestedObject(); - statJson["id"] = "EMS Reads (Tx)"; + statJson["id"] = "1"; statJson["s"] = EMSESP::txservice_.telegram_read_count(); statJson["f"] = EMSESP::txservice_.telegram_read_fail_count(); statJson["q"] = EMSESP::txservice_.read_quality(); statJson = statsJson.createNestedObject(); - statJson["id"] = "EMS Writes (Tx)"; + statJson["id"] = "2"; statJson["s"] = EMSESP::txservice_.telegram_write_count(); statJson["f"] = EMSESP::txservice_.telegram_write_fail_count(); statJson["q"] = EMSESP::txservice_.write_quality(); if (EMSESP::dallassensor_.dallas_enabled()) { statJson = statsJson.createNestedObject(); - statJson["id"] = "Temperature Sensor Reads"; + statJson["id"] = "3"; statJson["s"] = EMSESP::dallassensor_.reads(); statJson["f"] = EMSESP::dallassensor_.fails(); statJson["q"] = EMSESP::dallassensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::dallassensor_.fails()) / EMSESP::dallassensor_.reads()); } if (EMSESP::analog_enabled()) { statJson = statsJson.createNestedObject(); - statJson["id"] = "Analog Sensor Reads"; + statJson["id"] = "4"; statJson["s"] = EMSESP::analogsensor_.reads(); statJson["f"] = EMSESP::analogsensor_.fails(); statJson["q"] = EMSESP::analogsensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::analogsensor_.fails()) / EMSESP::analogsensor_.reads()); } if (Mqtt::enabled()) { statJson = statsJson.createNestedObject(); - statJson["id"] = "MQTT Publishes"; + statJson["id"] = "5"; statJson["s"] = Mqtt::publish_count(); statJson["f"] = Mqtt::publish_fails(); statJson["q"] = Mqtt::publish_count() == 0 ? 100 : 100 - (uint8_t)((100 * Mqtt::publish_fails()) / (Mqtt::publish_count() + Mqtt::publish_fails())); } statJson = statsJson.createNestedObject(); - statJson["id"] = "API Calls"; + statJson["id"] = "6"; statJson["s"] = WebAPIService::api_count(); // + WebAPIService::api_fails(); statJson["f"] = WebAPIService::api_fails(); statJson["q"] = @@ -190,7 +190,7 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) { #ifndef EMSESP_STANDALONE if (EMSESP::system_.syslog_enabled()) { statJson = statsJson.createNestedObject(); - statJson["id"] = "Syslog Messages"; + statJson["id"] = "7"; statJson["s"] = EMSESP::system_.syslog_count(); statJson["f"] = EMSESP::system_.syslog_fails(); statJson["q"] = EMSESP::system_.syslog_count() == 0