diff --git a/js/common/util/compute_domain.js b/js/common/util/compute_domain.js new file mode 100644 index 0000000000..58faa51be7 --- /dev/null +++ b/js/common/util/compute_domain.js @@ -0,0 +1,7 @@ +export default function computeDomain(stateObj) { + if (!stateObj._domain) { + stateObj._domain = stateObj.entity_id.substr(0, stateObj.entity_id.indexOf('.')); + } + + return stateObj._domain; +} diff --git a/js/common/util/compute_state_display.js b/js/common/util/compute_state_display.js new file mode 100644 index 0000000000..a43175de4a --- /dev/null +++ b/js/common/util/compute_state_display.js @@ -0,0 +1,59 @@ +import computeDomain from './compute_domain'; +import formatDateTime from './format_date_time'; +import formatDate from './format_date'; +import formatTime from './format_time'; + +export default function computeStateDisplay(haLocalize, stateObj, language) { + if (!stateObj._stateDisplay) { + const domain = computeDomain(stateObj); + if (domain === 'binary_sensor') { + // Try device class translation, then default binary sensor translation + if (stateObj.attributes.device_class) { + stateObj._stateDisplay = + haLocalize(`state.${domain}.${stateObj.attributes.device_class}`, stateObj.state); + } + if (!stateObj._stateDisplay) { + stateObj._stateDisplay = haLocalize(`state.${domain}.default`, stateObj.state); + } + } else if (stateObj.attributes.unit_of_measurement) { + stateObj._stateDisplay = stateObj.state + ' ' + stateObj.attributes.unit_of_measurement; + } else if (domain === 'input_datetime') { + let date; + if (!stateObj.attributes.has_time) { + date = new Date( + stateObj.attributes.year, + stateObj.attributes.month - 1, + stateObj.attributes.day + ); + stateObj._stateDisplay = formatDate(date, language); + } else if (!stateObj.attributes.has_date) { + date = new Date( + 1970, 0, 1, + stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatTime(date, language); + } else { + date = new Date( + stateObj.attributes.year, stateObj.attributes.month - 1, + stateObj.attributes.day, stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatDateTime(date, language); + } + } else if (domain === 'zwave') { + if (['initializing', 'dead'].includes(stateObj.state)) { + stateObj._stateDisplay = haLocalize('state.zwave.query_stage', stateObj.state, 'query_stage', stateObj.attributes.query_stage); + } else { + stateObj._stateDisplay = haLocalize('state.zwave.default', stateObj.state); + } + } else { + stateObj._stateDisplay = haLocalize(`state.${domain}`, stateObj.state); + } + // Fall back to default or raw state if nothing else matches. + stateObj._stateDisplay = stateObj._stateDisplay + || haLocalize('state.default', stateObj.state) || stateObj.state; + } + + return stateObj._stateDisplay; +} diff --git a/js/common/util/format_date.js b/js/common/util/format_date.js new file mode 100644 index 0000000000..006e736f88 --- /dev/null +++ b/js/common/util/format_date.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleDateStringSupportsOptions() { + try { + new Date().toLocaleDateString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleDateStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleDateString( + locales, + { year: 'numeric', month: 'long', day: 'numeric' }, + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'mediumDate'); + }); diff --git a/js/common/util/format_date_time.js b/js/common/util/format_date_time.js new file mode 100644 index 0000000000..f695511b86 --- /dev/null +++ b/js/common/util/format_date_time.js @@ -0,0 +1,22 @@ +// Check for support of native locale string options +function toLocaleStringSupportsOptions() { + try { + new Date().toLocaleString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleString(locales, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'haDateTime'); + }); diff --git a/js/common/util/format_time.js b/js/common/util/format_time.js new file mode 100644 index 0000000000..5ff05a67da --- /dev/null +++ b/js/common/util/format_time.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleTimeStringSupportsOptions() { + try { + new Date().toLocaleTimeString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleTimeStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleTimeString( + locales, + { hour: 'numeric', minute: '2-digit' } + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'shortTime'); + }); diff --git a/js/util.js b/js/util.js index 621f7e0019..eb97c013ac 100644 --- a/js/util.js +++ b/js/util.js @@ -7,7 +7,22 @@ */ import attributeClassNames from './common/util/attribute_class_names'; +import computeDomain from './common/util/compute_domain'; +import computeStateDisplay from './common/util/compute_state_display'; +import formatDate from './common/util/format_date'; +import formatDateTime from './common/util/format_date_time'; +import formatTime from './common/util/format_time'; window.hassUtil = window.hassUtil || {}; +const language = navigator.languages ? + navigator.languages[0] : navigator.language || navigator.userLanguage; + +window.fecha.masks.haDateTime = window.fecha.masks.shortTime + ' ' + window.fecha.masks.mediumDate; + window.hassUtil.attributeClassNames = attributeClassNames; +window.hassUtil.computeDomain = computeDomain; +window.hassUtil.computeStateDisplay = computeStateDisplay; +window.hassUtil.formatDate = dateObj => formatDate(dateObj, language); +window.hassUtil.formatDateTime = dateObj => formatDateTime(dateObj, language); +window.hassUtil.formatTime = dateObj => formatTime(dateObj, language); diff --git a/src/components/ha-cards.html b/src/components/ha-cards.html index e4d35670ea..f6e81a4ff5 100644 --- a/src/components/ha-cards.html +++ b/src/components/ha-cards.html @@ -7,6 +7,8 @@ + + diff --git a/src/home-assistant.html b/src/home-assistant.html index 56c549a09f..587808d958 100644 --- a/src/home-assistant.html +++ b/src/home-assistant.html @@ -2,7 +2,6 @@ - diff --git a/src/state-summary/state-card-display.html b/src/state-summary/state-card-display.html index dbb0a061e7..411158c411 100644 --- a/src/state-summary/state-card-display.html +++ b/src/state-summary/state-card-display.html @@ -3,6 +3,8 @@ + + @@ -20,7 +22,7 @@ - [[computeStateDisplay(haLocalize, stateObj)]] + [[computeStateDisplay(haLocalize, stateObj, language)]] @@ -40,55 +42,8 @@ class StateCardDisplay extends window.hassMixins.LocalizeMixin(Polymer.Element) }; } - computeStateDisplay(haLocalize, stateObj) { - if (!stateObj._stateDisplay) { - const domain = window.hassUtil.computeDomain(stateObj); - if (domain === 'binary_sensor') { - // Try device class translation, then default binary sensor translation - stateObj._stateDisplay = - haLocalize(`state.${domain}.${stateObj.attributes.device_class}`, stateObj.state) - || haLocalize(`state.${domain}.default`, stateObj.state); - } else if (stateObj.attributes.unit_of_measurement) { - stateObj._stateDisplay = stateObj.state + ' ' + stateObj.attributes.unit_of_measurement; - } else if (domain === 'input_datetime') { - let date; - if (!stateObj.attributes.has_time) { - date = new Date( - stateObj.attributes.year, - stateObj.attributes.month - 1, - stateObj.attributes.day - ); - stateObj._stateDisplay = window.hassUtil.formatDate(date); - } else if (!stateObj.attributes.has_date) { - date = new Date( - 1970, 0, 1, - stateObj.attributes.hour, - stateObj.attributes.minute - ); - stateObj._stateDisplay = window.hassUtil.formatTime(date); - } else { - date = new Date( - stateObj.attributes.year, stateObj.attributes.month - 1, - stateObj.attributes.day, stateObj.attributes.hour, - stateObj.attributes.minute - ); - stateObj._stateDisplay = window.hassUtil.formatDateTime(date); - } - } else if (domain === 'zwave') { - if (['initializing', 'dead'].includes(stateObj.state)) { - stateObj._stateDisplay = haLocalize('state.zwave.query_stage', stateObj.state, 'query_stage', stateObj.attributes.query_stage); - } else { - stateObj._stateDisplay = haLocalize('state.zwave.default', stateObj.state); - } - } else { - stateObj._stateDisplay = haLocalize(`state.${domain}`, stateObj.state); - } - // Fall back to default or raw state if nothing else matches. - stateObj._stateDisplay = stateObj._stateDisplay - || haLocalize('state.default', stateObj.state) || stateObj.state; - } - - return stateObj._stateDisplay; + computeStateDisplay(haLocalize, stateObj, language) { + return window.hassUtil.computeStateDisplay(haLocalize, stateObj, language); } } customElements.define(StateCardDisplay.is, StateCardDisplay); diff --git a/src/util/hass-mixins.html b/src/util/hass-mixins.html index 219db5fc35..cf200353f5 100644 --- a/src/util/hass-mixins.html +++ b/src/util/hass-mixins.html @@ -1,3 +1,5 @@ + +