purifier-card 2.6.9 → 2.7.0

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.
@@ -0,0 +1,26 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import globals from 'globals';
3
+ import tsParser from '@typescript-eslint/parser';
4
+ import tsPlugin from '@typescript-eslint/eslint-plugin';
5
+ import importPlugin from 'eslint-plugin-import';
6
+ import js from '@eslint/js';
7
+
8
+ export default defineConfig([
9
+ {
10
+ files: ['**/*.ts', '**/*.js', '**/*.mjs'],
11
+ languageOptions: {
12
+ globals: globals.browser,
13
+ ecmaVersion: 2020,
14
+ sourceType: 'module',
15
+ parser: tsParser,
16
+ },
17
+ plugins: {
18
+ '@typescript-eslint': tsPlugin,
19
+ import: importPlugin,
20
+ },
21
+ rules: {
22
+ ...js.configs.recommended.rules,
23
+ ...tsPlugin.configs.recommended.rules,
24
+ },
25
+ },
26
+ ]);
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "purifier-card",
3
- "version": "2.6.9",
3
+ "version": "2.7.0",
4
4
  "description": "Air Purifier card for Home Assistant Lovelace UI",
5
5
  "main": "dist/purifier-card.js",
6
6
  "scripts": {
7
7
  "start": "rollup -c --watch",
8
- "lint": "eslint src",
8
+ "lint": "npm run lint:src && npm run lint:translations",
9
9
  "lint:fix": "eslint src --fix",
10
+ "lint:src": "eslint src",
11
+ "lint:translations": "node scripts/validate-i18n",
10
12
  "format": "prettier --write .",
11
13
  "build": "rollup -c",
12
14
  "test": "npm run lint && npm run build",
@@ -32,42 +34,44 @@
32
34
  },
33
35
  "license": "MIT",
34
36
  "dependencies": {
35
- "@types/lodash": "^4.14.195",
36
37
  "custom-card-helpers": "^2.0.0",
37
- "ha-template": "^1.2.2",
38
- "home-assistant-js-websocket": "^9.1.0",
38
+ "ha-template": "^1.4.0",
39
+ "home-assistant-js-websocket": "^9.6.0",
39
40
  "lit": "^3.3.2",
40
41
  "lodash": "^4.17.21"
41
42
  },
42
43
  "devDependencies": {
43
- "@babel/core": "^7.9.6",
44
- "@babel/plugin-transform-runtime": "^7.17.0",
45
- "@babel/preset-env": "^7.16.11",
46
- "@rollup/plugin-babel": "^6.0.3",
44
+ "@babel/core": "^7.28.5",
45
+ "@babel/plugin-transform-runtime": "^7.28.5",
46
+ "@babel/preset-env": "^7.28.5",
47
+ "@eslint/js": "^9.39.2",
48
+ "@rollup/plugin-babel": "^6.1.0",
47
49
  "@rollup/plugin-commonjs": "^29.0.0",
48
- "@rollup/plugin-image": "^3.0.1",
49
- "@rollup/plugin-json": "^6.0.0",
50
+ "@rollup/plugin-image": "^3.0.3",
51
+ "@rollup/plugin-json": "^6.1.0",
50
52
  "@rollup/plugin-node-resolve": "^16.0.3",
51
53
  "@rollup/plugin-replace": "^6.0.3",
52
54
  "@rollup/plugin-terser": "^0.4.4",
53
55
  "@semantic-release/git": "^10.0.1",
54
- "@typescript-eslint/eslint-plugin": "^8.54.0",
55
- "@typescript-eslint/parser": "^8.54.0",
56
- "eslint": "^8.57.0",
57
- "eslint-config-prettier": "^9.1.0",
58
- "eslint-plugin-import": "^2.20.2",
59
- "husky": "^9.0.11",
56
+ "@types/lodash": "^4.14.195",
57
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
58
+ "@typescript-eslint/parser": "^8.51.0",
59
+ "eslint": "^9.39.2",
60
+ "eslint-config-prettier": "^10.1.8",
61
+ "eslint-plugin-import": "^2.32.0",
62
+ "globals": "^17.0.0",
63
+ "husky": "^9.1.7",
60
64
  "lint-staged": "^16.3.1",
61
65
  "postcss-preset-env": "^11.1.2",
62
- "prettier": "^3.2.5",
66
+ "prettier": "^3.7.4",
63
67
  "rollup": "^4.59.0",
64
- "rollup-plugin-html-literals": "^2.0.1",
68
+ "rollup-plugin-minify-html-literals-v3": "^1.3.4",
65
69
  "rollup-plugin-postcss": "^4.0.2",
66
- "rollup-plugin-postcss-lit": "^2.0.0",
67
- "rollup-plugin-serve": "^2.0.1",
70
+ "rollup-plugin-postcss-lit": "^2.2.0",
71
+ "rollup-plugin-serve": "^3.0.0",
68
72
  "rollup-plugin-typescript2": "^0.36.0",
69
73
  "semantic-release": "^25.0.3",
70
- "typescript": "^5.1.3"
74
+ "typescript": "^5.9.3"
71
75
  },
72
76
  "browserslist": [
73
77
  "last 2 versions",
package/rollup.config.mjs CHANGED
@@ -10,7 +10,7 @@ import postcss from 'rollup-plugin-postcss';
10
10
  import postcssPresetEnv from 'postcss-preset-env';
11
11
  import postcssLit from 'rollup-plugin-postcss-lit';
12
12
  import terser from '@rollup/plugin-terser';
13
- import minifyLiterals from 'rollup-plugin-html-literals';
13
+ import minifyLiterals from 'rollup-plugin-minify-html-literals-v3';
14
14
  import replace from '@rollup/plugin-replace';
15
15
  import serve from 'rollup-plugin-serve';
16
16
 
@@ -61,11 +61,12 @@ const plugins = [
61
61
  !IS_DEV && minifyLiterals(),
62
62
  !IS_DEV &&
63
63
  terser({
64
+ maxWorkers: 1,
64
65
  output: {
65
66
  comments: false,
66
67
  },
67
68
  }),
68
- ];
69
+ ].filter(Boolean);
69
70
 
70
71
  export default {
71
72
  input: 'src/purifier-card.ts',
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readdir, readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import process from 'node:process';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const translationsDir = path.join(__dirname, '..', 'src', 'translations');
10
+ const sourceLocale = 'en.json';
11
+
12
+ const flattenKeys = (value, prefix = '') => {
13
+ let keys = [];
14
+ if (value && typeof value === 'object') {
15
+ for (const [key, child] of Object.entries(value)) {
16
+ const nextPrefix = prefix ? `${prefix}.${key}` : key;
17
+ keys = keys.concat(flattenKeys(child, nextPrefix));
18
+ }
19
+ } else if (prefix) {
20
+ keys.push(prefix);
21
+ }
22
+ return keys;
23
+ };
24
+
25
+ const readJson = async (filePath) => {
26
+ const raw = await readFile(filePath, 'utf8');
27
+ return JSON.parse(raw);
28
+ };
29
+
30
+ const listJsonFiles = async () => {
31
+ const files = await readdir(translationsDir);
32
+ return files.filter((file) => file.endsWith('.json')).sort();
33
+ };
34
+
35
+ const main = async () => {
36
+ const files = await listJsonFiles();
37
+
38
+ if (!files.includes(sourceLocale)) {
39
+ console.error(`Missing source locale: ${sourceLocale}`);
40
+ process.exit(1);
41
+ }
42
+
43
+ const sourcePath = path.join(translationsDir, sourceLocale);
44
+ const sourceData = await readJson(sourcePath);
45
+ const sourceKeys = new Set(flattenKeys(sourceData));
46
+
47
+ let hasErrors = false;
48
+
49
+ for (const file of files) {
50
+ if (file === sourceLocale) continue;
51
+
52
+ const localePath = path.join(translationsDir, file);
53
+ const localeData = await readJson(localePath);
54
+ const localeKeys = flattenKeys(localeData);
55
+ const extraKeys = localeKeys.filter((key) => !sourceKeys.has(key));
56
+
57
+ if (extraKeys.length > 0) {
58
+ hasErrors = true;
59
+ console.error(
60
+ `Extra keys found in ${file} (missing in ${sourceLocale}):`,
61
+ );
62
+ for (const key of extraKeys.sort()) {
63
+ console.error(` - ${key}`);
64
+ }
65
+ }
66
+ }
67
+
68
+ if (hasErrors) {
69
+ process.exit(1);
70
+ }
71
+
72
+ console.log('Translation keys are consistent with en.json.');
73
+ };
74
+
75
+ main().catch((error) => {
76
+ console.error('Failed to validate translations:', error);
77
+ process.exit(1);
78
+ });
@@ -1,5 +1,6 @@
1
1
  import { CSSResultGroup, LitElement, PropertyValues, html, nothing } from 'lit';
2
2
  import { customElement, property, state } from 'lit/decorators.js';
3
+ import { repeat } from 'lit/directives/repeat.js';
3
4
  import {
4
5
  hasConfigOrEntityChanged,
5
6
  fireEvent,
@@ -130,11 +131,59 @@ export class PurifierCard extends LitElement {
130
131
  }
131
132
  }
132
133
 
133
- private handlePresetMode(event: PointerEvent) {
134
- const preset_mode = (<HTMLDivElement>event.target).getAttribute('value');
134
+ private handlePresetMode(
135
+ e: CustomEvent<{ item?: { value?: string } }>,
136
+ ): void {
137
+ const preset_mode = e.detail.item?.value;
135
138
  this.callService('fan.set_preset_mode', { preset_mode });
136
139
  }
137
140
 
141
+ private renderDropdown({
142
+ icon,
143
+ value,
144
+ options,
145
+ onSelect,
146
+ formatLabel,
147
+ ariaLabel,
148
+ }: {
149
+ icon: string;
150
+ value: string;
151
+ options: string[];
152
+ onSelect: (_e: CustomEvent<{ item?: { value?: string } }>) => void;
153
+ formatLabel: (_value: string) => string;
154
+ ariaLabel?: string;
155
+ }): Template {
156
+ const selectedLabel = formatLabel(value);
157
+
158
+ return html`
159
+ <div class="tip dropdown-tip" @click=${(e: Event) => e.stopPropagation()}>
160
+ <ha-dropdown placement="bottom" @wa-select=${onSelect}>
161
+ <button
162
+ class="dropdown-trigger"
163
+ slot="trigger"
164
+ aria-label=${ariaLabel ?? selectedLabel}
165
+ >
166
+ <ha-icon icon=${icon}></ha-icon>
167
+ <span class="tip-title">${selectedLabel}</span>
168
+ <ha-icon
169
+ class="dropdown-trigger-arrow"
170
+ icon="mdi:menu-down"
171
+ ></ha-icon>
172
+ </button>
173
+ ${repeat(
174
+ options,
175
+ (item) => item,
176
+ (item) => html`
177
+ <ha-dropdown-item .value=${item} ?checked=${item === value}>
178
+ ${formatLabel(item)}
179
+ </ha-dropdown-item>
180
+ `,
181
+ )}
182
+ </ha-dropdown>
183
+ </div>
184
+ `;
185
+ }
186
+
138
187
  private handlePercentage(event: CustomEvent<SliderValue>) {
139
188
  const percentage = event.detail.value;
140
189
  this.callService('fan.set_percentage', { percentage });
@@ -154,32 +203,15 @@ export class PurifierCard extends LitElement {
154
203
  return nothing;
155
204
  }
156
205
 
157
- const selected = preset_modes.indexOf(preset_mode);
158
-
159
- return html`
160
- <div class="tip preset-mode">
161
- <ha-dropdown @click="${(e: PointerEvent) => e.stopPropagation()}">
162
- <mmp-icon-button slot="trigger">
163
- <ha-icon icon="mdi:fan"></ha-icon>
164
- <span>
165
- ${localize(`preset_mode.${preset_mode}`) || preset_mode}
166
- </span>
167
- </mmp-icon-button>
168
-
169
- ${preset_modes.map(
170
- (item, index) => html`
171
- <ha-dropdown-item
172
- ?activated=${selected === index}
173
- value=${item}
174
- @click=${(e: PointerEvent) => this.handlePresetMode(e)}
175
- >
176
- ${localize(`preset_mode.${item.toLowerCase()}`) || item}
177
- </ha-dropdown-item>
178
- `,
179
- )}
180
- </ha-dropdown>
181
- </div>
182
- `;
206
+ return this.renderDropdown({
207
+ icon: 'mdi:fan',
208
+ value: preset_mode,
209
+ options: preset_modes,
210
+ onSelect: (e) => this.handlePresetMode(e),
211
+ formatLabel: (value: string) =>
212
+ localize(`preset_mode.${value.toLowerCase()}`) ?? value,
213
+ ariaLabel: localize('common.preset_mode') || 'Preset mode',
214
+ });
183
215
  }
184
216
 
185
217
  private renderAQI(): Template {
@@ -271,13 +303,12 @@ export class PurifierCard extends LitElement {
271
303
 
272
304
  return html`
273
305
  <div class="state">
306
+ ${this.requestInProgress
307
+ ? html`<ha-spinner class="state-spinner" size="tiny"></ha-spinner>`
308
+ : nothing}
274
309
  <span class="state-text" alt=${localizedState}>
275
310
  ${localizedState}
276
311
  </span>
277
- <ha-circular-progress
278
- .indeterminate=${this.requestInProgress}
279
- size="small"
280
- ></ha-circular-progress>
281
312
  </div>
282
313
  `;
283
314
  }
package/src/styles.css CHANGED
@@ -46,15 +46,53 @@ ha-card {
46
46
  gap: var(--pc-spacing);
47
47
  flex-grow: 1;
48
48
  flex-wrap: wrap;
49
+ align-items: center;
49
50
  padding: var(--pc-spacing);
50
51
 
51
52
  & .tip {
52
53
  cursor: pointer;
54
+ display: inline-flex;
55
+ align-items: center;
56
+ gap: 4px;
57
+
58
+ & ha-icon {
59
+ --mdc-icon-size: 18px;
60
+ }
61
+ }
62
+
63
+ & .dropdown-tip {
64
+ display: inline-flex;
65
+ align-items: center;
66
+ gap: 4px;
67
+ }
68
+
69
+ & .dropdown-trigger {
70
+ display: inline-flex;
71
+ align-items: center;
72
+ gap: 4px;
73
+ background: transparent;
74
+ border: 0;
75
+ color: var(--pc-secondary-text-color);
76
+ cursor: pointer;
77
+ font: inherit;
78
+ line-height: 1;
79
+ padding: 0;
80
+ }
81
+
82
+ & .dropdown-trigger:focus-visible {
83
+ outline: 2px solid var(--primary-color);
84
+ outline-offset: 2px;
53
85
  }
54
- }
55
86
 
56
- .preset-mode ha-icon {
57
- display: inline-block;
87
+ & .dropdown-trigger-arrow {
88
+ --mdc-icon-size: 18px;
89
+ }
90
+
91
+ & .tip-title {
92
+ display: inline-block;
93
+ line-height: 1;
94
+ vertical-align: middle;
95
+ }
58
96
  }
59
97
 
60
98
  .more-info {
@@ -148,6 +186,8 @@ ha-card {
148
186
  display: flex;
149
187
  align-items: center;
150
188
  justify-content: center;
189
+ gap: var(--pc-spacing);
190
+ direction: ltr;
151
191
  }
152
192
 
153
193
  .state-text {
@@ -155,12 +195,10 @@ ha-card {
155
195
  white-space: nowrap;
156
196
  text-overflow: ellipsis;
157
197
  overflow: hidden;
158
- margin-left: calc(28px + var(--pc-spacing)); /* size + margin of spinner */
159
198
  }
160
199
 
161
- .state mwc-circular-progress {
162
- --mdc-theme-primary: var(--pc-secondary-text-color) !important;
163
- margin-left: var(--pc-spacing);
200
+ .state .state-spinner {
201
+ --ha-spinner-color: var(--pc-secondary-text-color);
164
202
  }
165
203
 
166
204
  .friendly-name {
@@ -3,7 +3,8 @@
3
3
  "name": "Карта Пречиствател за Въздух",
4
4
  "description": "Картата Пречиствател за Въздух улеснява управлението на различни видове смарт пречистватели.",
5
5
  "not_available": "Обектът не е наличен",
6
- "toggle_power": "Включи/Изключи"
6
+ "toggle_power": "Включи/Изключи",
7
+ "preset_mode": "Предварителен режим"
7
8
  },
8
9
  "state": {
9
10
  "on": "Включен",
@@ -13,10 +14,15 @@
13
14
  "auto": "Автоматичен режим",
14
15
  "silent": "Тих режим",
15
16
  "favorite": "Любима",
16
- "fan": "Вентилатор"
17
+ "fan": "Вентилатор",
18
+ "idle": "Неактивен",
19
+ "low": "Ниска",
20
+ "medium": "Средна",
21
+ "high": "Висока"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "Избирането на обект е задължително!"
24
+ "missing_entity": "Избирането на обект е задължително!",
25
+ "invalid_config": "Невалидна конфигурация на картата!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Обект (Задължително)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Покажи лентата с инструменти",
34
40
  "show_toolbar_aria_label_off": "Скрий лентата с инструменти",
35
41
  "code_only_note": "Забележка: Настройването на actions и stats е възможно единствено чрез Code Editor."
42
+ },
43
+ "warning": {
44
+ "actions_array": "ПРЕДУПРЕЖДЕНИЕ: 'actions' е преименувано на 'shortcuts'"
36
45
  }
37
46
  }
@@ -3,7 +3,8 @@
3
3
  "name": "Purifier Card",
4
4
  "description": "Purifier card us permet controlar el purificador intel·ligent.",
5
5
  "not_available": "L'entitat no està disponible",
6
- "toggle_power": "Encendre/apagar"
6
+ "toggle_power": "Encendre/apagar",
7
+ "preset_mode": "Mode predefinit"
7
8
  },
8
9
  "state": {
9
10
  "on": "Encès",
@@ -13,10 +14,15 @@
13
14
  "auto": "Auto",
14
15
  "silent": "Silenciós",
15
16
  "favorite": "Favorit",
16
- "fan": "Ventilador"
17
+ "fan": "Ventilador",
18
+ "idle": "Inactiu",
19
+ "low": "Baix",
20
+ "medium": "Mitjà",
21
+ "high": "Alt"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "Cal especificar una entitat."
24
+ "missing_entity": "Cal especificar una entitat.",
25
+ "invalid_config": "Configuració de targeta no vàlida!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Entitat (Requerit)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Mostra barra d'eines",
34
40
  "show_toolbar_aria_label_off": "Amaga barra d'eines",
35
41
  "code_only_note": "Nota: Configuració de les accions i estadístiques només disponible des de l'Editor de Codi."
42
+ },
43
+ "warning": {
44
+ "actions_array": "AVÍS: 'actions' s'ha reanomenat a 'shortcuts'"
36
45
  }
37
46
  }
@@ -3,7 +3,8 @@
3
3
  "name": "Karta čističky",
4
4
  "description": "Karta čističky Vám umožní ovládat Vaši chytrou čističku.",
5
5
  "not_available": "Entita je nedostupná",
6
- "toggle_power": "Zapnout/vypnout"
6
+ "toggle_power": "Zapnout/vypnout",
7
+ "preset_mode": "Režim předvolby"
7
8
  },
8
9
  "state": {
9
10
  "on": "Zapnuto",
@@ -13,10 +14,15 @@
13
14
  "auto": "Automatický",
14
15
  "silent": "Noční",
15
16
  "favorite": "Manuální",
16
- "fan": "Větrák"
17
+ "fan": "Větrák",
18
+ "idle": "Nečinný",
19
+ "low": "Nízký",
20
+ "medium": "Střední",
21
+ "high": "Vysoký"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "Je vyžadováno specifikování entity!"
24
+ "missing_entity": "Je vyžadováno specifikování entity!",
25
+ "invalid_config": "Neplatná konfigurace karty!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Entity (povinné)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Zapnout zobrazení lišty",
34
40
  "show_toolbar_aria_label_off": "Vypnout zobrazení lišty",
35
41
  "code_only_note": "Poznámka: Nastavení akcí a statistik je dostupné pouze v editoru kódu."
42
+ },
43
+ "warning": {
44
+ "actions_array": "VAROVÁNÍ: 'actions' bylo přejmenováno na 'shortcuts'"
36
45
  }
37
46
  }
@@ -3,7 +3,8 @@
3
3
  "name": "Purifier Karte",
4
4
  "description": "Die Purifier Karte steuert deinen smarten Luftreiniger.",
5
5
  "not_available": "Entity nicht verfügbar",
6
- "toggle_power": "an/aus"
6
+ "toggle_power": "an/aus",
7
+ "preset_mode": "Voreingestellter Modus"
7
8
  },
8
9
  "state": {
9
10
  "on": "An",
@@ -13,10 +14,15 @@
13
14
  "auto": "Auto",
14
15
  "silent": "Leise",
15
16
  "favorite": "Favorit",
16
- "fan": "Lüfter"
17
+ "fan": "Lüfter",
18
+ "idle": "Leerlauf",
19
+ "low": "Niedrig",
20
+ "medium": "Mittel",
21
+ "high": "Hoch"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "Es muss eine Entity definiert werden!"
24
+ "missing_entity": "Es muss eine Entity definiert werden!",
25
+ "invalid_config": "Ungültige Kartenkonfiguration!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Entity (Erforderlich)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Symbolleiste anzeigen anschalten",
34
40
  "show_toolbar_aria_label_off": "Symbolleiste anzeigen ausschalten",
35
41
  "code_only_note": "Bitte beachten: Aktionen und Status Optionen sind nur im Code Editor verfügbar."
42
+ },
43
+ "warning": {
44
+ "actions_array": "WARNUNG: 'actions' wurde in 'shortcuts' umbenannt"
36
45
  }
37
46
  }
@@ -3,7 +3,8 @@
3
3
  "name": "Purifier Card",
4
4
  "description": "Purifier card allows you to control your smart purifier.",
5
5
  "not_available": "Entity is not available",
6
- "toggle_power": "Turn on/off"
6
+ "toggle_power": "Turn on/off",
7
+ "preset_mode": "Preset mode"
7
8
  },
8
9
  "state": {
9
10
  "on": "On",
@@ -13,10 +14,15 @@
13
14
  "auto": "Auto",
14
15
  "silent": "Silent",
15
16
  "favorite": "Favorite",
16
- "fan": "Fan"
17
+ "fan": "Fan",
18
+ "idle": "Idle",
19
+ "low": "Low",
20
+ "medium": "Medium",
21
+ "high": "High"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "Specifying entity is required!"
24
+ "missing_entity": "Specifying entity is required!",
25
+ "invalid_config": "Invalid card configuration!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Entity (Required)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Toggle display toolbar on",
34
40
  "show_toolbar_aria_label_off": "Toggle display toolbar off",
35
41
  "code_only_note": "Note: Setting actions and stats options are available exclusively using Code Editor."
42
+ },
43
+ "warning": {
44
+ "actions_array": "WARNING: 'actions' has been renamed to 'shortcuts'"
36
45
  }
37
46
  }
@@ -3,7 +3,8 @@
3
3
  "name": "Tarjeta Purificadora",
4
4
  "description": "La tarjeta purificadora te permite controlar tu purificador inteligente.",
5
5
  "not_available": "La entidad no está disponible",
6
- "toggle_power": "Encender/Apagar"
6
+ "toggle_power": "Encender/Apagar",
7
+ "preset_mode": "Modo preestablecido"
7
8
  },
8
9
  "state": {
9
10
  "on": "Encendido",
@@ -13,10 +14,15 @@
13
14
  "auto": "Automático",
14
15
  "silent": "Nocturno",
15
16
  "favorite": "Manual",
16
- "fan": "Ventilador"
17
+ "fan": "Ventilador",
18
+ "idle": "Inactivo",
19
+ "low": "Bajo",
20
+ "medium": "Medio",
21
+ "high": "Alto"
17
22
  },
18
23
  "error": {
19
- "missing_entity": "¡Se requiere especificar la entidad!"
24
+ "missing_entity": "¡Se requiere especificar la entidad!",
25
+ "invalid_config": "¡Configuración de tarjeta inválida!"
20
26
  },
21
27
  "editor": {
22
28
  "entity": "Entidad (Requerido)",
@@ -33,5 +39,8 @@
33
39
  "show_toolbar_aria_label_on": "Activar mostrar barra de herramientas",
34
40
  "show_toolbar_aria_label_off": "Desactivar mostrar barra de herramientas",
35
41
  "code_only_note": "Nota: La configuración de acciones y opciones de estadísticas solo está disponible mediante el Editor de Código."
42
+ },
43
+ "warning": {
44
+ "actions_array": "ADVERTENCIA: 'actions' ha sido renombrado a 'shortcuts'"
36
45
  }
37
46
  }