iobroker.flowers 0.3.9 → 0.4.1

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/README.md CHANGED
@@ -83,6 +83,14 @@ Only one watering cycle runs at a time per plant. Configure the duration in Sett
83
83
 
84
84
  ## Changelog
85
85
 
86
+ ### 0.4.1 (2026-06-20)
87
+ - (sadam6752-tech) Fix W5612: add missing i18n keys for Custom Profiles and placeholder fields
88
+ - (sadam6752-tech) Update engines.node to >=22; remove Node.js 20 from test matrix
89
+ - (sadam6752-tech) Add prettier.config.mjs, tsconfig.json, @types/node; update devDependencies
90
+
91
+ ### 0.4.0 (2026-05-14)
92
+ - (sadam6752-tech) Fix object hierarchy: change plants container from `channel` to `folder` type to allow device children
93
+
86
94
  ### 0.3.9 (2026-04-30)
87
95
  - (sadam6752-tech) Fix button state roles: set `read=false` for `sendDailyReport` and `sendWeeklyReport` buttons (required by ioBroker role spec)
88
96
 
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Automatische Bewässerung",
58
58
  "Watering Duration (min)": "Bewässerungszeit (Min.)",
59
59
  "Watering": "Bewässerung"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -56,5 +56,8 @@
56
56
  "Sansevieria Laurentii": "Sansevieria Laurentii",
57
57
  "Automatic Watering": "Automatic Watering",
58
58
  "Watering Duration (min)": "Watering Duration (min)",
59
- "Watering": "Watering"
59
+ "Watering": "Watering",
60
+ "name or leave empty": "name or leave empty",
61
+ "Custom Profiles": "Custom Profiles",
62
+ "user1,user2": "user1,user2"
60
63
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Riego automático",
58
58
  "Watering Duration (min)": "Duración del riego (min)",
59
59
  "Watering": "Riego"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Arrosage automatique",
58
58
  "Watering Duration (min)": "Durée d arrosage (min)",
59
59
  "Watering": "Arrosage"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Irrigazione automatica",
58
58
  "Watering Duration (min)": "Durata irrigazione (min)",
59
59
  "Watering": "Irrigazione"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Automatisch water geven",
58
58
  "Watering Duration (min)": "Bewateringstijd (min)",
59
59
  "Watering": "Bewatering"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Automatyczne podlewanie",
58
58
  "Watering Duration (min)": "Czas podlewania (min)",
59
59
  "Watering": "Podlewanie"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Rega automática",
58
58
  "Watering Duration (min)": "Duração da rega (min)",
59
59
  "Watering": "Rega"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Автополив",
58
58
  "Watering Duration (min)": "Время полива (мин.)",
59
59
  "Watering": "Полив"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "Автополив",
58
58
  "Watering Duration (min)": "Час поливу (хв.)",
59
59
  "Watering": "Полив"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
@@ -57,4 +57,8 @@
57
57
  "Automatic Watering": "自动浇水",
58
58
  "Watering Duration (min)": "浇水时长(分钟)",
59
59
  "Watering": "浇水"
60
+ ,
61
+ "name or leave empty": "name or leave empty",
62
+ "Custom Profiles": "Custom Profiles",
63
+ "user1,user2": "user1,user2"
60
64
  }
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "flowers",
4
- "version": "0.3.9",
4
+ "version": "0.4.1",
5
5
  "news": {
6
+ "0.4.1": {
7
+ "en": "Fix W5612: add missing i18n keys; update engines.node to >=22; add prettier.config.mjs, tsconfig.json, @types/node; update devDependencies",
8
+ "de": "W5612 behoben: fehlende i18n-Schlüssel hinzugefügt; engines.node auf >=22 aktualisiert; prettier.config.mjs, tsconfig.json, @types/node hinzugefügt; devDependencies aktualisiert",
9
+ "ru": "Исправление W5612: добавлены отсутствующие ключи i18n; engines.node обновлён до >=22; добавлены prettier.config.mjs, tsconfig.json, @types/node; обновлены devDependencies",
10
+ "fr": "Fix W5612: clés i18n manquantes ajoutées; engines.node mis à jour à >=22; prettier.config.mjs, tsconfig.json, @types/node ajoutés; devDependencies mis à jour",
11
+ "it": "Fix W5612: chiavi i18n mancanti aggiunti; engines.node aggiornato a >=22; prettier.config.mjs, tsconfig.json, @types/node aggiunti; devDependencies aggiornati",
12
+ "es": "Fix W5612: claves i18n faltantes añadidas; engines.node actualizado a >=22; prettier.config.mjs, tsconfig.json, @types/node añadidos; devDependencies actualizados",
13
+ "pl": "Naprawa W5612: dodano brakujące klucze i18n; engines.node zaktualizowano do >=22; dodano prettier.config.mjs, tsconfig.json, @types/node; zaktualizowano devDependencies",
14
+ "pt": "Fix W5612: chaves i18n em falta adicionadas; engines.node atualizado para >=22; prettier.config.mjs, tsconfig.json, @types/node adicionados; devDependencies atualizados",
15
+ "nl": "Fix W5612: ontbrekende i18n-sleutels toegevoegd; engines.node bijgewerkt naar >=22; prettier.config.mjs, tsconfig.json, @types/node toegevoegd; devDependencies bijgewerkt",
16
+ "uk": "Виправлення W5612: додано відсутні ключі i18n; engines.node оновлено до >=22; додано prettier.config.mjs, tsconfig.json, @types/node; оновлено devDependencies",
17
+ "zh-cn": "修复W5612:添加缺失的i18n键;将engines.node更新为>=22;添加prettier.config.mjs、tsconfig.json、@types/node;更新devDependencies"
18
+ },
19
+ "0.4.0": {
20
+ "en": "Fix object hierarchy: change plants container from channel to folder type to allow device children",
21
+ "de": "Objekthierarchie korrigiert: plants-Container von channel auf folder geändert, damit device-Kinder erlaubt sind",
22
+ "ru": "Исправлена иерархия объектов: контейнер plants изменён с channel на folder для поддержки дочерних device",
23
+ "fr": "Correction hiérarchie objets: conteneur plants changé de channel à folder pour autoriser les enfants device",
24
+ "it": "Corretta gerarchia oggetti: contenitore plants cambiato da channel a folder per consentire figli device",
25
+ "es": "Corrección jerarquía objetos: contenedor plants cambiado de channel a folder para permitir hijos device",
26
+ "pl": "Poprawiono hierarchię obiektów: kontener plants zmieniony z channel na folder, aby umożliwić dzieci device",
27
+ "pt": "Correção hierarquia objetos: contentor plants alterado de channel para folder para permitir filhos device",
28
+ "nl": "Objecthiërarchie gecorrigeerd: plants-container gewijzigd van channel naar folder om device-kinderen toe te staan",
29
+ "uk": "Виправлено ієрархію об'єктів: контейнер plants змінено з channel на folder для підтримки дочірніх device",
30
+ "zh-cn": "修复对象层次结构:将plants容器从channel类型改为folder类型以允许device子对象"
31
+ },
6
32
  "0.3.9": {
7
33
  "en": "Fix button state roles: set read=false for sendDailyReport and sendWeeklyReport buttons",
8
34
  "de": "Button-Rollen korrigiert: read=false für sendDailyReport und sendWeeklyReport gesetzt",
@@ -80,19 +106,6 @@
80
106
  "nl": "Unit-tests toegevoegd voor MonitorService, NotificationManager en messages; README bijgewerkt met apparaatlinks; mocha verwijderd uit devDependencies",
81
107
  "uk": "Додано unit-тести для MonitorService, NotificationManager та messages; оновлено README з посиланнями на пристрої; видалено mocha з devDependencies",
82
108
  "zh-cn": "为MonitorService、NotificationManager和messages添加单元测试;更新README添加设备链接;从devDependencies中删除mocha"
83
- },
84
- "0.3.3": {
85
- "en": "Fix object hierarchy (device/channel/state), correct state roles (value.humidity, value.temperature, value.battery), improve unload cleanup",
86
- "de": "Objekthierarchie korrigiert (device/channel/state), korrekte State-Rollen, verbessertes Aufräumen beim Entladen",
87
- "ru": "Исправлена иерархия объектов (device/channel/state), правильные роли состояний, улучшена очистка при выгрузке",
88
- "fr": "Correction hiérarchie objets (device/channel/state), rôles d'état corrects, nettoyage amélioré au déchargement",
89
- "it": "Corretta gerarchia oggetti (device/channel/state), ruoli stato corretti, pulizia migliorata allo scaricamento",
90
- "es": "Corrección jerarquía objetos (device/channel/state), roles de estado correctos, limpieza mejorada al descargar",
91
- "pl": "Poprawiono hierarchię obiektów (device/channel/state), poprawne role stanów, ulepszone czyszczenie przy wyładowaniu",
92
- "pt": "Correção hierarquia objetos (device/channel/state), funções de estado corretas, limpeza melhorada no descarregamento",
93
- "nl": "Objecthiërarchie gecorrigeerd (device/channel/state), correcte state-rollen, verbeterde opruiming bij ontladen",
94
- "uk": "Виправлено ієрархію об'єктів (device/channel/state), правильні ролі станів, покращено очищення при вивантаженні",
95
- "zh-cn": "修复对象层次结构(device/channel/state),正确的状态角色,改进卸载清理"
96
109
  }
97
110
  },
98
111
  "titleLang": {
package/lib/messages.js CHANGED
@@ -1,174 +1,114 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  /**
4
4
  * Localized alert messages for the flowers adapter.
5
5
  * Supported languages: en, de, ru, fr, it, es, pl, pt, nl, uk, zh-cn
6
6
  */
7
7
  const MESSAGES = {
8
- humidity_low: {
9
- en: (label, val, min) =>
10
- `💧 ${label}: soil too DRY — ${val}% (min ${min}%). Time to water!`,
11
- de: (label, val, min) =>
12
- `💧 ${label}: Erde zu TROCKEN — ${val}% (min ${min}%). Zeit zum Gießen!`,
13
- ru: (label, val, min) =>
14
- `💧 ${label}: почва слишком СУХАЯ — ${val}% (мин ${min}%). Пора поливать!`,
15
- fr: (label, val, min) =>
16
- `💧 ${label}: terre trop SÈCHE — ${val}% (min ${min}%). Il faut arroser!`,
17
- it: (label, val, min) =>
18
- `💧 ${label}: terra troppo SECCA — ${val}% (min ${min}%). È ora di annaffiare!`,
19
- es: (label, val, min) =>
20
- `💧 ${label}: tierra demasiado SECA — ${val}% (mín ${min}%). ¡Hora de regar!`,
21
- pl: (label, val, min) =>
22
- `💧 ${label}: gleba zbyt SUCHA — ${val}% (min ${min}%). Czas podlać!`,
23
- pt: (label, val, min) =>
24
- `💧 ${label}: terra muito SECA — ${val}% (mín ${min}%). Hora de regar!`,
25
- nl: (label, val, min) =>
26
- `💧 ${label}: grond te DROOG — ${val}% (min ${min}%). Tijd om water te geven!`,
27
- uk: (label, val, min) =>
28
- `💧 ${label}: ґрунт занадто СУХИЙ — ${val}% (мін ${min}%). Час поливати!`,
29
- "zh-cn": (label, val, min) =>
30
- `💧 ${label}: 土壤太干 — ${val}% (最低 ${min}%). 该浇水了!`,
31
- },
32
- humidity_high: {
33
- en: (label, val, max) =>
34
- `💦 ${label}: soil too WET — ${val}% (max ${max}%). Check drainage!`,
35
- de: (label, val, max) =>
36
- `💦 ${label}: Erde zu NASS — ${val}% (max ${max}%). Drainage prüfen!`,
37
- ru: (label, val, max) =>
38
- `💦 ${label}: почва слишком ВЛАЖНАЯ — ${val}% (макс ${max}%). Проверьте дренаж!`,
39
- fr: (label, val, max) =>
40
- `💦 ${label}: terre trop HUMIDE — ${val}% (max ${max}%). Vérifiez le drainage!`,
41
- it: (label, val, max) =>
42
- `💦 ${label}: terra troppo UMIDA — ${val}% (max ${max}%). Controlla il drenaggio!`,
43
- es: (label, val, max) =>
44
- `💦 ${label}: tierra demasiado HÚMEDA — ${val}% (máx ${max}%). ¡Revisa el drenaje!`,
45
- pl: (label, val, max) =>
46
- `💦 ${label}: gleba zbyt MOKRA — ${val}% (max ${max}%). Sprawdź drenaż!`,
47
- pt: (label, val, max) =>
48
- `💦 ${label}: terra muito ÚMIDA — ${val}% (máx ${max}%). Verifique a drenagem!`,
49
- nl: (label, val, max) =>
50
- `💦 ${label}: grond te NAT — ${val}% (max ${max}%). Controleer de afwatering!`,
51
- uk: (label, val, max) =>
52
- `💦 ${label}: ґрунт занадто ВОЛОГИЙ — ${val}% (макс ${max}%). Перевірте дренаж!`,
53
- "zh-cn": (label, val, max) =>
54
- `💦 ${label}: 土壤太湿 — ${val}% (最高 ${max}%). 检查排水!`,
55
- },
56
- temp_low: {
57
- en: (label, val, min) => `🥶 ${label}: too COLD — ${val}°C (min ${min}°C)`,
58
- de: (label, val, min) => `🥶 ${label}: zu KALT — ${val}°C (min ${min}°C)`,
59
- ru: (label, val, min) =>
60
- `🥶 ${label}: слишком ХОЛОДНО — ${val}°C (мин ${min}°C)`,
61
- fr: (label, val, min) =>
62
- `🥶 ${label}: trop FROID — ${val}°C (min ${min}°C)`,
63
- it: (label, val, min) =>
64
- `🥶 ${label}: troppo FREDDO — ${val}°C (min ${min}°C)`,
65
- es: (label, val, min) =>
66
- `🥶 ${label}: demasiado FRÍO — ${val}°C (mín ${min}°C)`,
67
- pl: (label, val, min) =>
68
- `🥶 ${label}: zbyt ZIMNO — ${val}°C (min ${min}°C)`,
69
- pt: (label, val, min) =>
70
- `🥶 ${label}: muito FRIO — ${val}°C (mín ${min}°C)`,
71
- nl: (label, val, min) => `🥶 ${label}: te KOUD — ${val}°C (min ${min}°C)`,
72
- uk: (label, val, min) =>
73
- `🥶 ${label}: занадто ХОЛОДНО — ${val}°C (мін ${min}°C)`,
74
- "zh-cn": (label, val, min) =>
75
- `🥶 ${label}: 太冷 ${val}°C (最低 ${min}°C)`,
76
- },
77
- temp_high: {
78
- en: (label, val, max) => `🥵 ${label}: too HOT ${val}°C (max ${max}°C)`,
79
- de: (label, val, max) => `🥵 ${label}: zu HEISS ${val}°C (max ${max}°C)`,
80
- ru: (label, val, max) =>
81
- `🥵 ${label}: слишком ЖАРКО ${val}°C (макс ${max}°C)`,
82
- fr: (label, val, max) =>
83
- `🥵 ${label}: trop CHAUD ${val}°C (max ${max}°C)`,
84
- it: (label, val, max) =>
85
- `🥵 ${label}: troppo CALDO — ${val}°C (max ${max}°C)`,
86
- es: (label, val, max) =>
87
- `🥵 ${label}: demasiado CALIENTE ${val}°C (máx ${max}°C)`,
88
- pl: (label, val, max) =>
89
- `🥵 ${label}: zbyt GORĄCO ${val}°C (max ${max}°C)`,
90
- pt: (label, val, max) =>
91
- `🥵 ${label}: muito QUENTE ${val}°C (máx ${max}°C)`,
92
- nl: (label, val, max) => `🥵 ${label}: te HEET — ${val}°C (max ${max}°C)`,
93
- uk: (label, val, max) =>
94
- `🥵 ${label}: занадто ЖАРКО ${val}°C (макс ${max}°C)`,
95
- "zh-cn": (label, val, max) =>
96
- `🥵 ${label}: 太热 ${val}°C (最高 ${max}°C)`,
97
- },
98
- battery_low: {
99
- en: (label, val, min) =>
100
- `🔋 ${label}: battery LOW ${val}% (min ${min}%). Replace battery!`,
101
- de: (label, val, min) =>
102
- `🔋 ${label}: Batterie SCHWACH ${val}% (min ${min}%). Batterie wechseln!`,
103
- ru: (label, val, min) =>
104
- `🔋 ${label}: батарея РАЗРЯЖЕНА ${val}% (мин ${min}%). Замените батарею!`,
105
- fr: (label, val, min) =>
106
- `🔋 ${label}: batterie FAIBLE ${val}% (min ${min}%). Remplacez la batterie!`,
107
- it: (label, val, min) =>
108
- `🔋 ${label}: batteria SCARICA — ${val}% (min ${min}%). Sostituire la batteria!`,
109
- es: (label, val, min) =>
110
- `🔋 ${label}: batería BAJA — ${val}% (mín ${min}%). ¡Reemplaza la batería!`,
111
- pl: (label, val, min) =>
112
- `🔋 ${label}: bateria SŁABA — ${val}% (min ${min}%). Wymień baterię!`,
113
- pt: (label, val, min) =>
114
- `🔋 ${label}: bateria FRACA — ${val}% (mín ${min}%). Substitua a bateria!`,
115
- nl: (label, val, min) =>
116
- `🔋 ${label}: batterij LAAG — ${val}% (min ${min}%). Vervang de batterij!`,
117
- uk: (label, val, min) =>
118
- `🔋 ${label}: батарея РОЗРЯДЖЕНА — ${val}% (мін ${min}%). Замініть батарею!`,
119
- "zh-cn": (label, val, min) =>
120
- `🔋 ${label}: 电池电量低 — ${val}% (最低 ${min}%). 请更换电池!`,
121
- },
122
- offline: {
123
- en: (label, hours) =>
124
- `📡 ${label}: sensor OFFLINE for ${hours}h. Check connection!`,
125
- de: (label, hours) =>
126
- `📡 ${label}: Sensor OFFLINE seit ${hours}h. Verbindung prüfen!`,
127
- ru: (label, hours) =>
128
- `📡 ${label}: датчик ОФЛАЙН ${hours}ч. Проверьте подключение!`,
129
- fr: (label, hours) =>
130
- `📡 ${label}: capteur HORS LIGNE depuis ${hours}h. Vérifiez la connexion!`,
131
- it: (label, hours) =>
132
- `📡 ${label}: sensore OFFLINE da ${hours}h. Controlla la connessione!`,
133
- es: (label, hours) =>
134
- `📡 ${label}: sensor DESCONECTADO por ${hours}h. ¡Revisa la conexión!`,
135
- pl: (label, hours) =>
136
- `📡 ${label}: czujnik OFFLINE od ${hours}h. Sprawdź połączenie!`,
137
- pt: (label, hours) =>
138
- `📡 ${label}: sensor OFFLINE há ${hours}h. Verifique a conexão!`,
139
- nl: (label, hours) =>
140
- `📡 ${label}: sensor OFFLINE voor ${hours}u. Controleer de verbinding!`,
141
- uk: (label, hours) =>
142
- `📡 ${label}: датчик ОФЛАЙН ${hours}год. Перевірте підключення!`,
143
- "zh-cn": (label, hours) =>
144
- `📡 ${label}: 传感器离线 ${hours}小时. 请检查连接!`,
145
- },
146
- report_header: {
147
- en: () => "🌿 Daily Plant Report",
148
- de: () => "🌿 Täglicher Pflanzenbericht",
149
- ru: () => "🌿 Ежедневный отчёт о растениях",
150
- fr: () => "🌿 Rapport quotidien des plantes",
151
- it: () => "🌿 Rapporto giornaliero piante",
152
- es: () => "🌿 Informe diario de plantas",
153
- pl: () => "🌿 Dzienny raport roślin",
154
- pt: () => "🌿 Relatório diário de plantas",
155
- nl: () => "🌿 Dagelijks plantenrapport",
156
- uk: () => "🌿 Щоденний звіт про рослини",
157
- "zh-cn": () => "🌿 每日植物报告",
158
- },
159
- weekly_report_header: {
160
- en: () => "🌿 Weekly Plant Report",
161
- de: () => "🌿 Wöchentlicher Pflanzenbericht",
162
- ru: () => "🌿 Еженедельный отчёт о растениях",
163
- fr: () => "🌿 Rapport hebdomadaire des plantes",
164
- it: () => "🌿 Rapporto settimanale piante",
165
- es: () => "🌿 Informe semanal de plantas",
166
- pl: () => "🌿 Tygodniowy raport roślin",
167
- pt: () => "🌿 Relatório semanal de plantas",
168
- nl: () => "🌿 Wekelijks plantenrapport",
169
- uk: () => "🌿 Щотижневий звіт про рослини",
170
- "zh-cn": () => "🌿 每周植物报告",
171
- },
8
+ humidity_low: {
9
+ en: (label, val, min) => `💧 ${label}: soil too DRY — ${val}% (min ${min}%). Time to water!`,
10
+ de: (label, val, min) => `💧 ${label}: Erde zu TROCKEN — ${val}% (min ${min}%). Zeit zum Gießen!`,
11
+ ru: (label, val, min) => `💧 ${label}: почва слишком СУХАЯ — ${val}% (мин ${min}%). Пора поливать!`,
12
+ fr: (label, val, min) => `💧 ${label}: terre trop SÈCHE — ${val}% (min ${min}%). Il faut arroser!`,
13
+ it: (label, val, min) => `💧 ${label}: terra troppo SECCA — ${val}% (min ${min}%). È ora di annaffiare!`,
14
+ es: (label, val, min) => `💧 ${label}: tierra demasiado SECA — ${val}% (mín ${min}%). ¡Hora de regar!`,
15
+ pl: (label, val, min) => `💧 ${label}: gleba zbyt SUCHA — ${val}% (min ${min}%). Czas podlać!`,
16
+ pt: (label, val, min) => `💧 ${label}: terra muito SECA — ${val}% (mín ${min}%). Hora de regar!`,
17
+ nl: (label, val, min) => `💧 ${label}: grond te DROOG — ${val}% (min ${min}%). Tijd om water te geven!`,
18
+ uk: (label, val, min) => `💧 ${label}: ґрунт занадто СУХИЙ — ${val}% (мін ${min}%). Час поливати!`,
19
+ 'zh-cn': (label, val, min) => `💧 ${label}: 土壤太干 — ${val}% (最低 ${min}%). 该浇水了!`,
20
+ },
21
+ humidity_high: {
22
+ en: (label, val, max) => `💦 ${label}: soil too WET — ${val}% (max ${max}%). Check drainage!`,
23
+ de: (label, val, max) => `💦 ${label}: Erde zu NASS — ${val}% (max ${max}%). Drainage prüfen!`,
24
+ ru: (label, val, max) => `💦 ${label}: почва слишком ВЛАЖНАЯ — ${val}% (макс ${max}%). Проверьте дренаж!`,
25
+ fr: (label, val, max) => `💦 ${label}: terre trop HUMIDE — ${val}% (max ${max}%). Vérifiez le drainage!`,
26
+ it: (label, val, max) => `💦 ${label}: terra troppo UMIDA — ${val}% (max ${max}%). Controlla il drenaggio!`,
27
+ es: (label, val, max) => `💦 ${label}: tierra demasiado HÚMEDA — ${val}% (máx ${max}%). ¡Revisa el drenaje!`,
28
+ pl: (label, val, max) => `💦 ${label}: gleba zbyt MOKRA — ${val}% (max ${max}%). Sprawdź drenaż!`,
29
+ pt: (label, val, max) => `💦 ${label}: terra muito ÚMIDA — ${val}% (máx ${max}%). Verifique a drenagem!`,
30
+ nl: (label, val, max) => `💦 ${label}: grond te NAT — ${val}% (max ${max}%). Controleer de afwatering!`,
31
+ uk: (label, val, max) => `💦 ${label}: ґрунт занадто ВОЛОГИЙ — ${val}% (макс ${max}%). Перевірте дренаж!`,
32
+ 'zh-cn': (label, val, max) => `💦 ${label}: 土壤太湿 — ${val}% (最高 ${max}%). 检查排水!`,
33
+ },
34
+ temp_low: {
35
+ en: (label, val, min) => `🥶 ${label}: too COLD — ${val}°C (min ${min}°C)`,
36
+ de: (label, val, min) => `🥶 ${label}: zu KALT — ${val}°C (min ${min}°C)`,
37
+ ru: (label, val, min) => `🥶 ${label}: слишком ХОЛОДНО — ${val}°C (мин ${min}°C)`,
38
+ fr: (label, val, min) => `🥶 ${label}: trop FROID — ${val}°C (min ${min}°C)`,
39
+ it: (label, val, min) => `🥶 ${label}: troppo FREDDO — ${val}°C (min ${min}°C)`,
40
+ es: (label, val, min) => `🥶 ${label}: demasiado FRÍO — ${val}°C (mín ${min}°C)`,
41
+ pl: (label, val, min) => `🥶 ${label}: zbyt ZIMNO — ${val}°C (min ${min}°C)`,
42
+ pt: (label, val, min) => `🥶 ${label}: muito FRIO — ${val}°C (mín ${min}°C)`,
43
+ nl: (label, val, min) => `🥶 ${label}: te KOUD — ${val}°C (min ${min}°C)`,
44
+ uk: (label, val, min) => `🥶 ${label}: занадто ХОЛОДНО — ${val}°C (мін ${min}°C)`,
45
+ 'zh-cn': (label, val, min) => `🥶 ${label}: 太冷 — ${val}°C (最低 ${min}°C)`,
46
+ },
47
+ temp_high: {
48
+ en: (label, val, max) => `🥵 ${label}: too HOT — ${val}°C (max ${max}°C)`,
49
+ de: (label, val, max) => `🥵 ${label}: zu HEISS — ${val}°C (max ${max}°C)`,
50
+ ru: (label, val, max) => `🥵 ${label}: слишком ЖАРКО — ${val}°C (макс ${max}°C)`,
51
+ fr: (label, val, max) => `🥵 ${label}: trop CHAUD — ${val}°C (max ${max}°C)`,
52
+ it: (label, val, max) => `🥵 ${label}: troppo CALDO — ${val}°C (max ${max}°C)`,
53
+ es: (label, val, max) => `🥵 ${label}: demasiado CALIENTE — ${val}°C (máx ${max}°C)`,
54
+ pl: (label, val, max) => `🥵 ${label}: zbyt GORĄCO — ${val}°C (max ${max}°C)`,
55
+ pt: (label, val, max) => `🥵 ${label}: muito QUENTE — ${val}°C (máx ${max}°C)`,
56
+ nl: (label, val, max) => `🥵 ${label}: te HEET — ${val}°C (max ${max}°C)`,
57
+ uk: (label, val, max) => `🥵 ${label}: занадто ЖАРКО — ${val}°C (макс ${max}°C)`,
58
+ 'zh-cn': (label, val, max) => `🥵 ${label}: 太热 — ${val}°C (最高 ${max}°C)`,
59
+ },
60
+ battery_low: {
61
+ en: (label, val, min) => `🔋 ${label}: battery LOW — ${val}% (min ${min}%). Replace battery!`,
62
+ de: (label, val, min) => `🔋 ${label}: Batterie SCHWACH — ${val}% (min ${min}%). Batterie wechseln!`,
63
+ ru: (label, val, min) => `🔋 ${label}: батарея РАЗРЯЖЕНА — ${val}% (мин ${min}%). Замените батарею!`,
64
+ fr: (label, val, min) => `🔋 ${label}: batterie FAIBLE — ${val}% (min ${min}%). Remplacez la batterie!`,
65
+ it: (label, val, min) => `🔋 ${label}: batteria SCARICA — ${val}% (min ${min}%). Sostituire la batteria!`,
66
+ es: (label, val, min) => `🔋 ${label}: batería BAJA — ${val}% (mín ${min}%). ¡Reemplaza la batería!`,
67
+ pl: (label, val, min) => `🔋 ${label}: bateria SŁABA — ${val}% (min ${min}%). Wymień baterię!`,
68
+ pt: (label, val, min) => `🔋 ${label}: bateria FRACA — ${val}% (mín ${min}%). Substitua a bateria!`,
69
+ nl: (label, val, min) => `🔋 ${label}: batterij LAAG — ${val}% (min ${min}%). Vervang de batterij!`,
70
+ uk: (label, val, min) => `🔋 ${label}: батарея РОЗРЯДЖЕНА — ${val}% (мін ${min}%). Замініть батарею!`,
71
+ 'zh-cn': (label, val, min) => `🔋 ${label}: 电池电量低 — ${val}% (最低 ${min}%). 请更换电池!`,
72
+ },
73
+ offline: {
74
+ en: (label, hours) => `📡 ${label}: sensor OFFLINE for ${hours}h. Check connection!`,
75
+ de: (label, hours) => `📡 ${label}: Sensor OFFLINE seit ${hours}h. Verbindung prüfen!`,
76
+ ru: (label, hours) => `📡 ${label}: датчик ОФЛАЙН ${hours}ч. Проверьте подключение!`,
77
+ fr: (label, hours) => `📡 ${label}: capteur HORS LIGNE depuis ${hours}h. Vérifiez la connexion!`,
78
+ it: (label, hours) => `📡 ${label}: sensore OFFLINE da ${hours}h. Controlla la connessione!`,
79
+ es: (label, hours) => `📡 ${label}: sensor DESCONECTADO por ${hours}h. ¡Revisa la conexión!`,
80
+ pl: (label, hours) => `📡 ${label}: czujnik OFFLINE od ${hours}h. Sprawdź połączenie!`,
81
+ pt: (label, hours) => `📡 ${label}: sensor OFFLINE ${hours}h. Verifique a conexão!`,
82
+ nl: (label, hours) => `📡 ${label}: sensor OFFLINE voor ${hours}u. Controleer de verbinding!`,
83
+ uk: (label, hours) => `📡 ${label}: датчик ОФЛАЙН ${hours}год. Перевірте підключення!`,
84
+ 'zh-cn': (label, hours) => `📡 ${label}: 传感器离线 ${hours}小时. 请检查连接!`,
85
+ },
86
+ report_header: {
87
+ en: () => '🌿 Daily Plant Report',
88
+ de: () => '🌿 Täglicher Pflanzenbericht',
89
+ ru: () => '🌿 Ежедневный отчёт о растениях',
90
+ fr: () => '🌿 Rapport quotidien des plantes',
91
+ it: () => '🌿 Rapporto giornaliero piante',
92
+ es: () => '🌿 Informe diario de plantas',
93
+ pl: () => '🌿 Dzienny raport roślin',
94
+ pt: () => '🌿 Relatório diário de plantas',
95
+ nl: () => '🌿 Dagelijks plantenrapport',
96
+ uk: () => '🌿 Щоденний звіт про рослини',
97
+ 'zh-cn': () => '🌿 每日植物报告',
98
+ },
99
+ weekly_report_header: {
100
+ en: () => '🌿 Weekly Plant Report',
101
+ de: () => '🌿 Wöchentlicher Pflanzenbericht',
102
+ ru: () => '🌿 Еженедельный отчёт о растениях',
103
+ fr: () => '🌿 Rapport hebdomadaire des plantes',
104
+ it: () => '🌿 Rapporto settimanale piante',
105
+ es: () => '🌿 Informe semanal de plantas',
106
+ pl: () => '🌿 Tygodniowy raport roślin',
107
+ pt: () => '🌿 Relatório semanal de plantas',
108
+ nl: () => '🌿 Wekelijks plantenrapport',
109
+ uk: () => '🌿 Щотижневий звіт про рослини',
110
+ 'zh-cn': () => '🌿 每周植物报告',
111
+ },
172
112
  };
173
113
 
174
114
  /**
@@ -176,16 +116,16 @@ const MESSAGES = {
176
116
  *
177
117
  * @param {string} key - message key
178
118
  * @param {string} lang - language code
179
- * @param {...any} args - message arguments
119
+ * @param {...string|number} args - message arguments
180
120
  * @returns {string} localized message string
181
121
  */
182
122
  function msg(key, lang, ...args) {
183
- const translations = MESSAGES[key];
184
- if (!translations) {
185
- return `[${key}]`;
186
- }
187
- const fn = translations[lang] || translations["en"];
188
- return fn(...args);
123
+ const translations = MESSAGES[key];
124
+ if (!translations) {
125
+ return `[${key}]`;
126
+ }
127
+ const fn = translations[lang] || translations['en'];
128
+ return fn(...args);
189
129
  }
190
130
 
191
131
  module.exports = { msg };