diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index fac0ab414..c7a11cb9e 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -68,7 +68,14 @@ const de: Translation = { 'MQTT Veröffentlicht', 'API Aufrufe', 'Syslog Mitteilungen' - ] + ], + NUM_DEVICES: '{num} Gerät{{en}}', + NUM_TEMP_SENSORS: '{num} Temperatursensor{{en}}', + NUM_ANALOG_SENSORS: '{num} Analoger Sensor{{en}}', + NUM_DAYS: '{num} Tag{{en}}', + NUM_SECONDS: '{num} Sekund{{en}}', + NUM_HOURS: '{num} Stunde{{n}}', + NUM_MINUTES: '{num} Minute{{en}}' }; export default de; diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index fe760415f..2c750d07a 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -68,7 +68,14 @@ const en: BaseTranslation = { 'MQTT Publishes', 'API Calls', 'Syslog Messages' - ] + ], + NUM_DEVICES: '{num} Device{{s}}', + NUM_TEMP_SENSORS: '{num} Temperature Sensor{{s}}', + NUM_ANALOG_SENSORS: '{num} Analog Sensor{{s}}', + NUM_DAYS: '{num} Day{{s}}', + NUM_SECONDS: '{num} Second{{s}}', + NUM_HOURS: '{num} Hour{{s}}', + NUM_MINUTES: '{num} Minute{{s}}' }; export default en; diff --git a/interface/src/i18n/i18n-types.ts b/interface/src/i18n/i18n-types.ts index 3e81fc391..5ba575a00 100644 --- a/interface/src/i18n/i18n-types.ts +++ b/interface/src/i18n/i18n-types.ts @@ -280,6 +280,41 @@ type RootTranslation = { */ '7': string } + /** + * {num} Device{{s}} + * @param {string | number | boolean} num + */ + NUM_DEVICES: RequiredParams<'num'> + /** + * {num} Temperature Sensor{{s}} + * @param {string | number | boolean} num + */ + NUM_TEMP_SENSORS: RequiredParams<'num'> + /** + * {num} Analog Sensor{{s}} + * @param {string | number | boolean} num + */ + NUM_ANALOG_SENSORS: RequiredParams<'num'> + /** + * {num} Day{{s}} + * @param {string | number | boolean} num + */ + NUM_DAYS: RequiredParams<'num'> + /** + * {num} Second{{s}} + * @param {string | number | boolean} num + */ + NUM_SECONDS: RequiredParams<'num'> + /** + * {num} Hour{{s}} + * @param {string | number | boolean} num + */ + NUM_HOURS: RequiredParams<'num'> + /** + * {num} Minute{{s}} + * @param {string | number | boolean} num + */ + NUM_MINUTES: RequiredParams<'num'> } export type TranslationFunctions = { @@ -545,6 +580,34 @@ export type TranslationFunctions = { */ '7': () => LocalizedString } + /** + * {num} Device{{s}} + */ + NUM_DEVICES: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Temperature Sensor{{s}} + */ + NUM_TEMP_SENSORS: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Analog Sensor{{s}} + */ + NUM_ANALOG_SENSORS: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Day{{s}} + */ + NUM_DAYS: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Second{{s}} + */ + NUM_SECONDS: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Hour{{s}} + */ + NUM_HOURS: (arg: { num: string | number | boolean }) => LocalizedString + /** + * {num} Minute{{s}} + */ + NUM_MINUTES: (arg: { num: string | number | boolean }) => LocalizedString } export type Formatters = {} diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index d5b43b3a3..532eef98c 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -49,8 +49,6 @@ import DeviceIcon from './DeviceIcon'; import { IconContext } from 'react-icons'; -import { formatDurationMin, pluralize } from '../utils'; - import { AuthenticatedContext } from '../contexts/authentication'; import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from '../components'; @@ -76,6 +74,8 @@ import { import { useI18nContext } from '../i18n/i18n-react'; +import parseMilliseconds from 'parse-ms'; + const DashboardData: FC = () => { const { me } = useContext(AuthenticatedContext); @@ -399,15 +399,32 @@ const DashboardData: FC = () => { const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c; + const formatDurationMin = (duration_min: number) => { + const { days, hours, minutes } = parseMilliseconds(duration_min * 60000); + let formatted = ''; + if (days) { + formatted += LL.NUM_DAYS({ num: days }) + ' '; + } + if (hours) { + formatted += LL.NUM_HOURS({ num: hours }) + ' '; + } + if (minutes) { + formatted += LL.NUM_MINUTES({ num: minutes }); + } + return formatted; + }; + function formatValue(value: any, uom: number) { if (value === undefined) { return ''; } switch (uom) { case DeviceValueUOM.HOURS: - return value ? formatDurationMin(value * 60) : '0 hours'; + return formatDurationMin(value * 60); case DeviceValueUOM.MINUTES: - return value ? formatDurationMin(value) : '0 minutes'; + return formatDurationMin(value); + case DeviceValueUOM.SECONDS: + return LL.NUM_SECONDS({ num: value }); case DeviceValueUOM.NONE: if (typeof value === 'number') { return new Intl.NumberFormat().format(value); @@ -423,8 +440,6 @@ const DashboardData: FC = () => { ' ' + DeviceValueUOM_s[uom] ); - case DeviceValueUOM.SECONDS: - return pluralize(value, DeviceValueUOM_s[uom]); default: return new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom]; } diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index eadf1bef4..04a9e5f69 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -32,7 +32,7 @@ import { ButtonRow, FormLoader, SectionContent } from '../components'; import { Status, busConnectionStatus, Stat } from './types'; -import { formatDurationSec, pluralize, extractErrorMessage, useRest } from '../utils'; +import { formatDurationSec, extractErrorMessage, useRest } from '../utils'; import * as EMSESP from './api'; @@ -195,11 +195,11 @@ const DashboardStatus: FC = () => { diff --git a/interface/src/utils/time.ts b/interface/src/utils/time.ts index 7a7986b52..f550e228f 100644 --- a/interface/src/utils/time.ts +++ b/interface/src/utils/time.ts @@ -1,5 +1,3 @@ -import parseMilliseconds from 'parse-ms'; - const LOCALE_FORMAT = new Intl.DateTimeFormat([...window.navigator.languages], { day: 'numeric', month: 'short', @@ -21,21 +19,6 @@ export const formatLocalDateTime = (date: Date) => { export const pluralize = (count: number, noun: string) => `${Intl.NumberFormat().format(count)} ${noun}${count !== 1 ? 's' : ''}`; -export const formatDurationMin = (duration_min: number) => { - const { days, hours, minutes } = parseMilliseconds(duration_min * 60000); - let formatted = ''; - if (days) { - formatted += pluralize(days, 'day') + ' '; - } - if (hours) { - formatted += pluralize(hours, 'hour') + ' '; - } - if (minutes) { - formatted += pluralize(minutes, 'minute') + ' '; - } - return formatted; -}; - export const formatDurationSec = (duration_sec: number) => { if (duration_sec === 0) { return ' ';