ha-nunjucks 1.7.4 → 1.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/filters.js +3 -3
- package/dist/globals.js +3 -3
- package/dist/index.js +4 -6
- package/dist/models/interfaces/hass.d.ts +46 -0
- package/dist/models/interfaces/hass.js +41 -1
- package/dist/utils/state_translated.d.ts +6 -4
- package/dist/utils/state_translated.js +120 -13
- package/package.json +1 -1
package/dist/filters.js
CHANGED
|
@@ -45,6 +45,9 @@ const HASS_FILTERS = {
|
|
|
45
45
|
state_translated,
|
|
46
46
|
attr_name_translated,
|
|
47
47
|
attr_value_translated,
|
|
48
|
+
number_translated,
|
|
49
|
+
date_translated,
|
|
50
|
+
datetime_translated,
|
|
48
51
|
// Groups
|
|
49
52
|
expand,
|
|
50
53
|
// Devices
|
|
@@ -92,9 +95,7 @@ const FILTERS = {
|
|
|
92
95
|
timestamp_local,
|
|
93
96
|
timestamp_utc,
|
|
94
97
|
timestamp_custom,
|
|
95
|
-
date_translated,
|
|
96
98
|
time_translated,
|
|
97
|
-
datetime_translated,
|
|
98
99
|
// To/From JSON
|
|
99
100
|
to_json,
|
|
100
101
|
from_json,
|
|
@@ -136,7 +137,6 @@ const FILTERS = {
|
|
|
136
137
|
ord,
|
|
137
138
|
multiply,
|
|
138
139
|
add,
|
|
139
|
-
number_translated,
|
|
140
140
|
// Type conversions
|
|
141
141
|
str,
|
|
142
142
|
// Functions and Filters to Process Raw Data
|
package/dist/globals.js
CHANGED
|
@@ -58,6 +58,9 @@ const HASS_GLOBALS = {
|
|
|
58
58
|
state_translated,
|
|
59
59
|
attr_name_translated,
|
|
60
60
|
attr_value_translated,
|
|
61
|
+
number_translated,
|
|
62
|
+
date_translated,
|
|
63
|
+
datetime_translated,
|
|
61
64
|
// Groups
|
|
62
65
|
expand,
|
|
63
66
|
// Entities
|
|
@@ -116,9 +119,7 @@ const GLOBALS = {
|
|
|
116
119
|
time_since,
|
|
117
120
|
time_until,
|
|
118
121
|
as_timedelta,
|
|
119
|
-
date_translated,
|
|
120
122
|
time_translated,
|
|
121
|
-
datetime_translated,
|
|
122
123
|
// Version
|
|
123
124
|
version,
|
|
124
125
|
// Numeric,
|
|
@@ -144,7 +145,6 @@ const GLOBALS = {
|
|
|
144
145
|
mod,
|
|
145
146
|
wrap,
|
|
146
147
|
remap,
|
|
147
|
-
number_translated,
|
|
148
148
|
// Type Conversions
|
|
149
149
|
set,
|
|
150
150
|
list,
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { subscribeConfigEntries } from './utils/config_entry';
|
|
|
8
8
|
import { fetchEntityRegistry } from './utils/entities';
|
|
9
9
|
import { fetchRepairsIssues } from './utils/issues';
|
|
10
10
|
import { fetchLabelRegistry } from './utils/labels';
|
|
11
|
+
import { getNumberFormatter, getTimeFormatter } from './utils/state_translated';
|
|
11
12
|
import { buildStatesObject } from './utils/states';
|
|
12
13
|
import { version } from './utils/version';
|
|
13
14
|
window.haNunjucks ||= {};
|
|
@@ -68,14 +69,11 @@ if (version(packageInfo.version).compare(window.haNunjucks.version || '0.0.0') >
|
|
|
68
69
|
// States object
|
|
69
70
|
buildStatesObject();
|
|
70
71
|
// Number and datetime translators
|
|
71
|
-
window.haNunjucks.numberFormat =
|
|
72
|
+
window.haNunjucks.numberFormat = getNumberFormatter(ha.hass);
|
|
72
73
|
window.haNunjucks.dateFormat = new Intl.DateTimeFormat(ha.hass.language, {
|
|
73
|
-
dateStyle: '
|
|
74
|
+
dateStyle: 'long',
|
|
74
75
|
});
|
|
75
|
-
window.haNunjucks.timeFormat =
|
|
76
|
-
timeStyle: 'long',
|
|
77
|
-
});
|
|
78
|
-
window.haNunjucks.datetimeFormat = new Intl.DateTimeFormat(ha.hass.language, { dateStyle: 'full', timeStyle: 'long' });
|
|
76
|
+
window.haNunjucks.timeFormat = getTimeFormatter(ha.hass);
|
|
79
77
|
window.haNunjucks.ordinalFormat = new Intl.PluralRules('en-US', // ha.hass.language, // Use english for proper numeric suffixes
|
|
80
78
|
{ type: 'ordinal' });
|
|
81
79
|
console.info(`%c HA-NUNJUCKS v${packageInfo.version}`, 'color: white; font-weight: bold; background: darkgreen');
|
|
@@ -22,6 +22,7 @@ export interface HomeAssistant {
|
|
|
22
22
|
panelUrl: string;
|
|
23
23
|
language: string;
|
|
24
24
|
selectedLanguage: string | null;
|
|
25
|
+
locale: FrontendLocaleData;
|
|
25
26
|
suspendWhenHidden: boolean;
|
|
26
27
|
enableShortcuts: boolean;
|
|
27
28
|
vibrate: boolean;
|
|
@@ -40,3 +41,48 @@ export interface HomeAssistant {
|
|
|
40
41
|
export interface HassElement extends HTMLElement {
|
|
41
42
|
hass: HomeAssistant;
|
|
42
43
|
}
|
|
44
|
+
interface FrontendLocaleData {
|
|
45
|
+
language: string;
|
|
46
|
+
number_format: NumberFormat;
|
|
47
|
+
time_format: TimeFormat;
|
|
48
|
+
date_format: DateFormat;
|
|
49
|
+
first_weekday: FirstWeekday;
|
|
50
|
+
time_zone: TimeZone;
|
|
51
|
+
}
|
|
52
|
+
export declare enum NumberFormat {
|
|
53
|
+
language = "language",
|
|
54
|
+
system = "system",
|
|
55
|
+
comma_decimal = "comma_decimal",
|
|
56
|
+
decimal_comma = "decimal_comma",
|
|
57
|
+
quote_decimal = "quote_decimal",
|
|
58
|
+
space_comma = "space_comma",
|
|
59
|
+
none = "none"
|
|
60
|
+
}
|
|
61
|
+
export declare enum TimeFormat {
|
|
62
|
+
language = "language",
|
|
63
|
+
system = "system",
|
|
64
|
+
am_pm = "12",
|
|
65
|
+
twenty_four = "24"
|
|
66
|
+
}
|
|
67
|
+
export declare enum TimeZone {
|
|
68
|
+
local = "local",
|
|
69
|
+
server = "server"
|
|
70
|
+
}
|
|
71
|
+
export declare enum DateFormat {
|
|
72
|
+
language = "language",
|
|
73
|
+
system = "system",
|
|
74
|
+
DMY = "DMY",
|
|
75
|
+
MDY = "MDY",
|
|
76
|
+
YMD = "YMD"
|
|
77
|
+
}
|
|
78
|
+
export declare enum FirstWeekday {
|
|
79
|
+
language = "language",
|
|
80
|
+
monday = "monday",
|
|
81
|
+
tuesday = "tuesday",
|
|
82
|
+
wednesday = "wednesday",
|
|
83
|
+
thursday = "thursday",
|
|
84
|
+
friday = "friday",
|
|
85
|
+
saturday = "saturday",
|
|
86
|
+
sunday = "sunday"
|
|
87
|
+
}
|
|
88
|
+
export {};
|
|
@@ -1 +1,41 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var NumberFormat;
|
|
2
|
+
(function (NumberFormat) {
|
|
3
|
+
NumberFormat["language"] = "language";
|
|
4
|
+
NumberFormat["system"] = "system";
|
|
5
|
+
NumberFormat["comma_decimal"] = "comma_decimal";
|
|
6
|
+
NumberFormat["decimal_comma"] = "decimal_comma";
|
|
7
|
+
NumberFormat["quote_decimal"] = "quote_decimal";
|
|
8
|
+
NumberFormat["space_comma"] = "space_comma";
|
|
9
|
+
NumberFormat["none"] = "none";
|
|
10
|
+
})(NumberFormat || (NumberFormat = {}));
|
|
11
|
+
export var TimeFormat;
|
|
12
|
+
(function (TimeFormat) {
|
|
13
|
+
TimeFormat["language"] = "language";
|
|
14
|
+
TimeFormat["system"] = "system";
|
|
15
|
+
TimeFormat["am_pm"] = "12";
|
|
16
|
+
TimeFormat["twenty_four"] = "24";
|
|
17
|
+
})(TimeFormat || (TimeFormat = {}));
|
|
18
|
+
export var TimeZone;
|
|
19
|
+
(function (TimeZone) {
|
|
20
|
+
TimeZone["local"] = "local";
|
|
21
|
+
TimeZone["server"] = "server";
|
|
22
|
+
})(TimeZone || (TimeZone = {}));
|
|
23
|
+
export var DateFormat;
|
|
24
|
+
(function (DateFormat) {
|
|
25
|
+
DateFormat["language"] = "language";
|
|
26
|
+
DateFormat["system"] = "system";
|
|
27
|
+
DateFormat["DMY"] = "DMY";
|
|
28
|
+
DateFormat["MDY"] = "MDY";
|
|
29
|
+
DateFormat["YMD"] = "YMD";
|
|
30
|
+
})(DateFormat || (DateFormat = {}));
|
|
31
|
+
export var FirstWeekday;
|
|
32
|
+
(function (FirstWeekday) {
|
|
33
|
+
FirstWeekday["language"] = "language";
|
|
34
|
+
FirstWeekday["monday"] = "monday";
|
|
35
|
+
FirstWeekday["tuesday"] = "tuesday";
|
|
36
|
+
FirstWeekday["wednesday"] = "wednesday";
|
|
37
|
+
FirstWeekday["thursday"] = "thursday";
|
|
38
|
+
FirstWeekday["friday"] = "friday";
|
|
39
|
+
FirstWeekday["saturday"] = "saturday";
|
|
40
|
+
FirstWeekday["sunday"] = "sunday";
|
|
41
|
+
})(FirstWeekday || (FirstWeekday = {}));
|
|
@@ -3,7 +3,9 @@ import { HomeAssistant } from '../models/interfaces/hass';
|
|
|
3
3
|
export declare function state_translated(hass: HomeAssistant, entity_id: string, state?: string): string;
|
|
4
4
|
export declare function attr_name_translated(hass: HomeAssistant, entity_id: string, attr_name: string): string;
|
|
5
5
|
export declare function attr_value_translated(hass: HomeAssistant, entity_id: string, attr_name: string, attr_value?: string): any;
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
6
|
+
export declare function getNumberFormatter(hass: HomeAssistant): Intl.NumberFormat;
|
|
7
|
+
export declare function number_translated(hass: HomeAssistant, value: number, precision?: number): string | number;
|
|
8
|
+
export declare function date_translated(hass: HomeAssistant, value: date | datetime | Date | string): string | date | datetime | Date;
|
|
9
|
+
export declare function getTimeFormatter(hass: HomeAssistant): Intl.DateTimeFormat;
|
|
10
|
+
export declare function time_translated(value: time | datetime | Date | string): string | datetime | Date | time;
|
|
11
|
+
export declare function datetime_translated(hass: HomeAssistant, value: datetime | Date | string): string | datetime | Date;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DateFormat, NumberFormat, TimeFormat, TimeZone, } from '../models/interfaces/hass';
|
|
1
2
|
export function state_translated(hass, entity_id, state) {
|
|
2
3
|
try {
|
|
3
4
|
return hass.formatEntityState(hass.states[entity_id], state);
|
|
@@ -11,9 +12,7 @@ export function attr_name_translated(hass, entity_id, attr_name) {
|
|
|
11
12
|
return hass.formatEntityAttributeName(hass.states[entity_id], attr_name);
|
|
12
13
|
}
|
|
13
14
|
catch {
|
|
14
|
-
return (attr_name ??
|
|
15
|
-
hass.states[entity_id]?.attributes?.[attr_name] ??
|
|
16
|
-
undefined);
|
|
15
|
+
return (attr_name ?? hass.states[entity_id]?.attributes?.[attr_name] ?? undefined);
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
export function attr_value_translated(hass, entity_id, attr_name, attr_value) {
|
|
@@ -21,43 +20,151 @@ export function attr_value_translated(hass, entity_id, attr_name, attr_value) {
|
|
|
21
20
|
return hass.formatEntityAttributeValue(hass.states[entity_id], attr_name, attr_value);
|
|
22
21
|
}
|
|
23
22
|
catch {
|
|
24
|
-
return (attr_value ??
|
|
25
|
-
hass.states[entity_id]?.attributes?.[attr_name] ??
|
|
26
|
-
undefined);
|
|
23
|
+
return (attr_value ?? hass.states[entity_id]?.attributes?.[attr_name] ?? undefined);
|
|
27
24
|
}
|
|
28
25
|
}
|
|
29
|
-
export function
|
|
26
|
+
export function getNumberFormatter(hass) {
|
|
27
|
+
// https://github.com/home-assistant/frontend/blob/52ac052baf139e94b7ed6891eb0beace7e2f47d3/src/common/number/format_number.ts#L24
|
|
28
|
+
let language;
|
|
29
|
+
switch (hass.locale.number_format) {
|
|
30
|
+
case NumberFormat.comma_decimal:
|
|
31
|
+
language = ['en-US', 'en']; // Use United States with fallback to English formatting 1,234,567.89
|
|
32
|
+
break;
|
|
33
|
+
case NumberFormat.decimal_comma:
|
|
34
|
+
language = ['de', 'es', 'it']; // Use German with fallback to Spanish then Italian formatting 1.234.567,89
|
|
35
|
+
break;
|
|
36
|
+
case NumberFormat.space_comma:
|
|
37
|
+
language = ['fr', 'sv', 'cs']; // Use French with fallback to Swedish and Czech formatting 1 234 567,89
|
|
38
|
+
break;
|
|
39
|
+
case NumberFormat.quote_decimal:
|
|
40
|
+
language = ['de-CH']; // Use German (Switzerland) formatting 1'234'567.89
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
language = hass.locale.language ?? hass.language;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
return new Intl.NumberFormat(language);
|
|
47
|
+
}
|
|
48
|
+
export function number_translated(hass, value, precision) {
|
|
30
49
|
value = Number(value);
|
|
31
50
|
if (isNaN(value)) {
|
|
32
51
|
return value;
|
|
33
52
|
}
|
|
34
53
|
if (precision) {
|
|
35
|
-
return value.toLocaleString(
|
|
54
|
+
return value.toLocaleString(hass.locale.language ?? hass.language, {
|
|
36
55
|
minimumFractionDigits: precision,
|
|
37
56
|
maximumFractionDigits: precision,
|
|
38
57
|
});
|
|
39
58
|
}
|
|
40
59
|
return window.haNunjucks.numberFormat.format(value);
|
|
41
60
|
}
|
|
42
|
-
export function date_translated(value) {
|
|
61
|
+
export function date_translated(hass, value) {
|
|
62
|
+
// https://github.com/home-assistant/frontend/blob/52ac052baf139e94b7ed6891eb0beace7e2f47d3/src/common/datetime/format_date.ts#L59
|
|
43
63
|
try {
|
|
44
|
-
|
|
64
|
+
let date;
|
|
65
|
+
if (typeof value === 'string') {
|
|
66
|
+
date = new Date(`${value}T00:00:00`);
|
|
67
|
+
}
|
|
68
|
+
else if (value instanceof Date) {
|
|
69
|
+
date = value;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
date = value.jsDate;
|
|
73
|
+
}
|
|
74
|
+
let order;
|
|
75
|
+
switch (hass.locale.date_format) {
|
|
76
|
+
case DateFormat.DMY:
|
|
77
|
+
order = ['day', 'month', 'year'];
|
|
78
|
+
break;
|
|
79
|
+
case DateFormat.MDY:
|
|
80
|
+
order = ['month', 'day', 'year'];
|
|
81
|
+
break;
|
|
82
|
+
case DateFormat.YMD:
|
|
83
|
+
order = ['year', 'month', 'day'];
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
return window.haNunjucks.dateFormat.format(date);
|
|
87
|
+
}
|
|
88
|
+
const parts = window.haNunjucks.dateFormat.formatToParts(date);
|
|
89
|
+
const partsObj = {
|
|
90
|
+
literal: parts.find((value) => value.type === 'literal')?.value,
|
|
91
|
+
day: parts.find((value) => value.type === 'day')?.value,
|
|
92
|
+
month: parts.find((value) => value.type === 'month')?.value,
|
|
93
|
+
year: parts.find((value) => value.type === 'year')?.value,
|
|
94
|
+
};
|
|
95
|
+
const lastPart = parts[parts.length - 1];
|
|
96
|
+
partsObj.lastLiteral = lastPart?.type === 'literal' ? lastPart?.value : '';
|
|
97
|
+
if (hass.locale.language === 'bg' &&
|
|
98
|
+
hass.locale.date_format === DateFormat.YMD) {
|
|
99
|
+
partsObj.lastLiteral = '';
|
|
100
|
+
}
|
|
101
|
+
return `${partsObj[order[0]]}${partsObj.literal}${partsObj[order[1]]}${partsObj.literal}${partsObj[order[2]]}${partsObj.lastLiteral}`;
|
|
45
102
|
}
|
|
46
103
|
catch {
|
|
47
104
|
return value;
|
|
48
105
|
}
|
|
49
106
|
}
|
|
107
|
+
function useAmPm(hass) {
|
|
108
|
+
// https://github.com/home-assistant/frontend/blob/52ac052baf139e94b7ed6891eb0beace7e2f47d3/src/common/datetime/use_am_pm.ts
|
|
109
|
+
if (hass.locale.time_format === TimeFormat.language ||
|
|
110
|
+
hass.locale.time_format === TimeFormat.system) {
|
|
111
|
+
const testLanguage = hass.locale.time_format === TimeFormat.language
|
|
112
|
+
? hass.locale.language
|
|
113
|
+
: undefined;
|
|
114
|
+
const test = new Date('January 1, 2023 22:00:00').toLocaleString(testLanguage);
|
|
115
|
+
return test.includes('10');
|
|
116
|
+
}
|
|
117
|
+
return hass.locale.time_format === TimeFormat.am_pm;
|
|
118
|
+
}
|
|
119
|
+
function resolveTimeZone(hass) {
|
|
120
|
+
// https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/resolve-time-zone.ts#L9
|
|
121
|
+
const intlTZ = Intl.DateTimeFormat?.().resolvedOptions?.().timeZone;
|
|
122
|
+
const localTZ = intlTZ ?? 'UTC';
|
|
123
|
+
return hass.locale.time_zone === TimeZone.local && intlTZ
|
|
124
|
+
? localTZ
|
|
125
|
+
: hass.config.time_zone;
|
|
126
|
+
}
|
|
127
|
+
export function getTimeFormatter(hass) {
|
|
128
|
+
const AMPM = useAmPm(hass);
|
|
129
|
+
const options = {
|
|
130
|
+
hour: AMPM ? 'numeric' : '2-digit',
|
|
131
|
+
minute: '2-digit',
|
|
132
|
+
hourCycle: AMPM ? 'h12' : 'h23',
|
|
133
|
+
timeZone: resolveTimeZone(hass),
|
|
134
|
+
};
|
|
135
|
+
return new Intl.DateTimeFormat(hass.locale.language ?? hass.language, options);
|
|
136
|
+
}
|
|
50
137
|
export function time_translated(value) {
|
|
51
138
|
try {
|
|
52
|
-
|
|
139
|
+
let time;
|
|
140
|
+
if (typeof value === 'string') {
|
|
141
|
+
time = new Date(`1970-01-01T${value}`);
|
|
142
|
+
}
|
|
143
|
+
else if (value instanceof Date) {
|
|
144
|
+
time = value;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
time = value.jsDate;
|
|
148
|
+
}
|
|
149
|
+
return window.haNunjucks.timeFormat.format(time);
|
|
53
150
|
}
|
|
54
151
|
catch {
|
|
55
152
|
return value;
|
|
56
153
|
}
|
|
57
154
|
}
|
|
58
|
-
export function datetime_translated(value) {
|
|
155
|
+
export function datetime_translated(hass, value) {
|
|
59
156
|
try {
|
|
60
|
-
|
|
157
|
+
let datetime;
|
|
158
|
+
if (typeof value === 'string') {
|
|
159
|
+
datetime = new Date(value);
|
|
160
|
+
}
|
|
161
|
+
else if (value instanceof Date) {
|
|
162
|
+
datetime = value;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
datetime = value.jsDate;
|
|
166
|
+
}
|
|
167
|
+
return `${date_translated(hass, datetime)} at ${time_translated(datetime)}`;
|
|
61
168
|
}
|
|
62
169
|
catch {
|
|
63
170
|
return value;
|