From cdf7d9465237d49cc5cb2fde93365747d98129f9 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Mon, 11 May 2026 01:38:40 +0300 Subject: [PATCH] feat(ui): expand card icon picker (44 -> 120 icons, +5 categories) Add 76 new icons to the custom card-icon picker and introduce five new categories: weather, nature, controls, status, office. Existing icon ids are unchanged so persisted card icons keep resolving. - icon-paths.ts: +36 Lucide path constants (weather, nature, room, office, media, hardware, lighting variants) - device-icons.ts: extend IconCategory union and CATEGORIES; add registry entries with labels + search aliases - en/ru/zh locales: 5 new category labels + 76 per-icon labels each (126 device.icon keys per locale, fully aligned) Tabs scroll horizontally via existing overflow-x; no migration needed (picker reads/writes ids by value, missing ids fall back to inheritance). --- .../ledgrab/static/js/core/device-icons.ts | 99 ++++++++++++++++++- .../src/ledgrab/static/js/core/icon-paths.ts | 58 +++++++++++ server/src/ledgrab/static/locales/en.json | 81 +++++++++++++++ server/src/ledgrab/static/locales/ru.json | 81 +++++++++++++++ server/src/ledgrab/static/locales/zh.json | 81 +++++++++++++++ 5 files changed, 398 insertions(+), 2 deletions(-) diff --git a/server/src/ledgrab/static/js/core/device-icons.ts b/server/src/ledgrab/static/js/core/device-icons.ts index 15f1b4a..12ed120 100644 --- a/server/src/ledgrab/static/js/core/device-icons.ts +++ b/server/src/ledgrab/static/js/core/device-icons.ts @@ -20,7 +20,12 @@ export type IconCategory = | 'rooms' | 'media' | 'signal' - | 'ambience'; + | 'ambience' + | 'weather' + | 'nature' + | 'controls' + | 'status' + | 'office'; export interface DeviceIconDef { /** Stable identifier — persisted on the entity. */ @@ -42,6 +47,11 @@ export const CATEGORIES: { id: IconCategory; label: string; i18n: string }[] = [ { id: 'media', label: 'Media', i18n: 'device.icon.cat.media' }, { id: 'signal', label: 'Signal', i18n: 'device.icon.cat.signal' }, { id: 'ambience', label: 'Ambience', i18n: 'device.icon.cat.ambience' }, + { id: 'weather', label: 'Weather', i18n: 'device.icon.cat.weather' }, + { id: 'nature', label: 'Nature', i18n: 'device.icon.cat.nature' }, + { id: 'controls', label: 'Controls', i18n: 'device.icon.cat.controls' }, + { id: 'status', label: 'Status', i18n: 'device.icon.cat.status' }, + { id: 'office', label: 'Office', i18n: 'device.icon.cat.office' }, ]; export const DEVICE_ICONS: DeviceIconDef[] = [ @@ -56,6 +66,16 @@ export const DEVICE_ICONS: DeviceIconDef[] = [ { id: 'headphones', paths: P.headphones, label: 'Headphones', aliases: ['headset', 'cans'], category: 'hardware' }, { id: 'usb', paths: P.usb, label: 'USB', aliases: ['cable', 'connector'], category: 'hardware' }, { id: 'plug', paths: P.plug, label: 'Power plug', aliases: ['outlet', 'socket'], category: 'hardware' }, + { id: 'phone', paths: P.smartphone, label: 'Phone', aliases: ['mobile', 'tablet', 'cell', 'smartphone'], category: 'hardware' }, + { id: 'package', paths: P.packageIcon, label: 'Device unit', aliases: ['box', 'package', 'module', 'crate'], category: 'hardware' }, + { id: 'code', paths: P.code, label: 'Code', aliases: ['script', 'firmware', 'dev'], category: 'hardware' }, + { id: 'laptop', paths: P.laptop, label: 'Laptop', aliases: ['notebook', 'macbook', 'computer'], category: 'hardware' }, + { id: 'server', paths: P.server, label: 'Server', aliases: ['rack', 'host', 'cluster', 'nas'], category: 'hardware' }, + { id: 'router', paths: P.router, label: 'Router', aliases: ['network', 'gateway', 'access point', 'ap'], category: 'hardware' }, + { id: 'webcam', paths: P.webcam, label: 'Webcam', aliases: ['cam', 'capture', 'video'], category: 'hardware' }, + { id: 'bot', paths: P.bot, label: 'Bot', aliases: ['robot', 'vacuum', 'automation', 'roomba'], category: 'hardware' }, + { id: 'watch', paths: P.watch, label: 'Smartwatch', aliases: ['wearable', 'wrist', 'fitness'], category: 'hardware' }, + { id: 'mcu', paths: P.memoryStick, label: 'Microcontroller', aliases: ['esp32', 'esp8266', 'arduino', 'mcu', 'chip', 'firmware'], category: 'hardware' }, // Lighting { id: 'bulb', paths: P.lightbulb, label: 'Bulb', aliases: ['lamp', 'light', 'lightbulb'], category: 'lighting' }, @@ -65,6 +85,15 @@ export const DEVICE_ICONS: DeviceIconDef[] = [ { id: 'lamp', paths: P.flaskConical, label: 'Floor lamp', aliases: ['standing', 'pendant'], category: 'lighting' }, { id: 'power', paths: P.power, label: 'Power', aliases: ['onoff', 'switch', 'standby'], category: 'lighting' }, { id: 'palette', paths: P.palette, label: 'Palette', aliases: ['color', 'colour', 'paint'], category: 'lighting' }, + { id: 'dim', paths: P.sunDim, label: 'Dim light', aliases: ['soft', 'low', 'mood'], category: 'lighting' }, + { id: 'ring', paths: P.circle, label: 'Ring light', aliases: ['halo', 'round', 'circle'], category: 'lighting' }, + { id: 'point', paths: P.circleDot, label: 'Point light', aliases: ['pinpoint', 'dot', 'pixel'], category: 'lighting' }, + { id: 'ceiling', paths: P.lampCeiling, label: 'Ceiling light', aliases: ['chandelier', 'pendant', 'hanging'], category: 'lighting' }, + { id: 'desk_lamp', paths: P.lampDesk, label: 'Desk lamp', aliases: ['task', 'workspace', 'pixar'], category: 'lighting' }, + { id: 'wall_light', paths: P.lampWallUp, label: 'Wall light', aliases: ['sconce', 'uplight', 'mounted'], category: 'lighting' }, + { id: 'flashlight', paths: P.flashlight, label: 'Flashlight', aliases: ['torch', 'beam', 'handheld'], category: 'lighting' }, + { id: 'bulb_off', paths: P.lightbulbOff, label: 'Bulb off', aliases: ['lightoff', 'dark', 'inactive', 'disabled'], category: 'lighting' }, + { id: 'candle', paths: P.candle, label: 'Candle', aliases: ['flame', 'wax', 'ambient', 'romantic'], category: 'lighting' }, // Rooms { id: 'bed', paths: P.bed, label: 'Bedroom', aliases: ['sleep', 'bedroom'], category: 'rooms' }, @@ -74,6 +103,10 @@ export const DEVICE_ICONS: DeviceIconDef[] = [ { id: 'home', paths: P.home, label: 'Home', aliases: ['house', 'household'], category: 'rooms' }, { id: 'fan', paths: P.fan, label: 'Fan', aliases: ['cooling', 'air'], category: 'rooms' }, { id: 'thermostat', paths: P.thermometer, label: 'Thermostat', aliases: ['temperature', 'heating', 'climate'], category: 'rooms' }, + { id: 'kitchen', paths: P.chefHat, label: 'Kitchen', aliases: ['cook', 'chef', 'food'], category: 'rooms' }, + { id: 'bath', paths: P.bath, label: 'Bathroom', aliases: ['bath', 'tub', 'shower'], category: 'rooms' }, + { id: 'garage', paths: P.warehouse, label: 'Garage', aliases: ['workshop', 'shed', 'storage'], category: 'rooms' }, + { id: 'outdoor', paths: P.trees, label: 'Outdoor', aliases: ['garden', 'yard', 'patio', 'park'], category: 'rooms' }, // Media { id: 'monitor', paths: P.monitor, label: 'Monitor', aliases: ['display', 'screen'], category: 'media' }, @@ -83,6 +116,11 @@ export const DEVICE_ICONS: DeviceIconDef[] = [ { id: 'speaker', paths: P.volume2, label: 'Speaker', aliases: ['audio', 'output', 'monitor'], category: 'media' }, { id: 'music', paths: P.music, label: 'Music', aliases: ['note', 'audio'], category: 'media' }, { id: 'film', paths: P.film, label: 'Film', aliases: ['video', 'movie', 'reel'], category: 'media' }, + { id: 'projector', paths: P.projector, label: 'Projector', aliases: ['beamer', 'cinema', 'home theater'], category: 'media' }, + { id: 'camcorder', paths: P.video, label: 'Camcorder', aliases: ['video', 'recorder', 'cam'], category: 'media' }, + { id: 'disc', paths: P.disc, label: 'Disc', aliases: ['vinyl', 'record', 'cd', 'dvd'], category: 'media' }, + { id: 'image', paths: P.image, label: 'Image', aliases: ['picture', 'photo', 'still'], category: 'media' }, + { id: 'audio_file', paths: P.fileAudio, label: 'Audio file', aliases: ['sound', 'sample', 'track'], category: 'media' }, // Signal { id: 'wifi', paths: P.wifi, label: 'Wi-Fi', aliases: ['wireless', 'network'], category: 'signal' }, @@ -91,16 +129,73 @@ export const DEVICE_ICONS: DeviceIconDef[] = [ { id: 'globe', paths: P.globe, label: 'Network', aliases: ['internet', 'web', 'world'], category: 'signal' }, { id: 'cloud', paths: P.cloudSun, label: 'Cloud', aliases: ['weather', 'mqtt'], category: 'signal' }, { id: 'gps', paths: P.mapPin, label: 'Location', aliases: ['map', 'gps', 'pin', 'place'], category: 'signal' }, + { id: 'send', paths: P.send, label: 'Send', aliases: ['push', 'publish', 'mqtt', 'transmit'], category: 'signal' }, // Ambience { id: 'sun', paths: P.sun, label: 'Sun', aliases: ['daylight', 'sunny', 'bright'], category: 'ambience' }, { id: 'moon', paths: P.moon, label: 'Moon', aliases: ['night', 'dark'], category: 'ambience' }, { id: 'flame', paths: P.flame, label: 'Flame', aliases: ['fire', 'candle', 'warm'], category: 'ambience' }, - { id: 'leaf', paths: P.leaf, label: 'Leaf', aliases: ['plant', 'eco', 'nature', 'green'], category: 'ambience' }, { id: 'star', paths: P.star, label: 'Star', aliases: ['favorite', 'special'], category: 'ambience' }, { id: 'sparkles', paths: P.sparkles, label: 'Sparkles', aliases: ['effect', 'magic', 'glow'], category: 'ambience' }, { id: 'gamepad', paths: P.gamepad2, label: 'Game', aliases: ['gaming', 'play'], category: 'ambience' }, { id: 'heart', paths: P.heart, label: 'Heart', aliases: ['love', 'favorite'], category: 'ambience' }, + + // Weather + { id: 'rain', paths: P.cloudRain, label: 'Rain', aliases: ['rainy', 'shower', 'drizzle', 'wet'], category: 'weather' }, + { id: 'snow', paths: P.cloudSnow, label: 'Snow', aliases: ['snowy', 'blizzard', 'cold'], category: 'weather' }, + { id: 'thunder', paths: P.cloudLightning, label: 'Thunder', aliases: ['lightning', 'storm', 'bolt'], category: 'weather' }, + { id: 'fog', paths: P.cloudFog, label: 'Fog', aliases: ['mist', 'haze', 'foggy'], category: 'weather' }, + { id: 'wind', paths: P.wind, label: 'Wind', aliases: ['breeze', 'gust', 'windy'], category: 'weather' }, + { id: 'snowflake', paths: P.snowflake, label: 'Snowflake', aliases: ['frost', 'ice', 'crystal'], category: 'weather' }, + { id: 'umbrella', paths: P.umbrella, label: 'Umbrella', aliases: ['rain', 'shelter', 'parasol'], category: 'weather' }, + { id: 'sunrise', paths: P.sunrise, label: 'Sunrise', aliases: ['dawn', 'morning', 'sunup'], category: 'weather' }, + { id: 'sunset', paths: P.sunset, label: 'Sunset', aliases: ['dusk', 'evening', 'twilight'], category: 'weather' }, + + // Nature + { id: 'tree', paths: P.treeDeciduous, label: 'Tree', aliases: ['plant', 'oak', 'forest', 'wood'], category: 'nature' }, + { id: 'flower', paths: P.flower2, label: 'Flower', aliases: ['bloom', 'blossom', 'garden'], category: 'nature' }, + { id: 'mountain', paths: P.mountain, label: 'Mountain', aliases: ['peak', 'hill', 'summit', 'alpine'], category: 'nature' }, + { id: 'waves', paths: P.waves, label: 'Waves', aliases: ['water', 'ocean', 'sea', 'ripple'], category: 'nature' }, + { id: 'sprout', paths: P.sprout, label: 'Sprout', aliases: ['seedling', 'shoot', 'grow', 'eco'], category: 'nature' }, + { id: 'water_drops', paths: P.droplets, label: 'Water drops', aliases: ['humidity', 'liquid', 'wet', 'splash'], category: 'nature' }, + { id: 'leaf', paths: P.leaf, label: 'Leaf', aliases: ['plant', 'eco', 'nature', 'green'], category: 'nature' }, + + // Controls + { id: 'switch', paths: P.toggleRight, label: 'Switch', aliases: ['toggle', 'on', 'off'], category: 'controls' }, + { id: 'slider', paths: P.slidersHorizontal, label: 'Slider', aliases: ['mixer', 'eq', 'level', 'dimmer'], category: 'controls' }, + { id: 'settings', paths: P.settings, label: 'Settings', aliases: ['cog', 'preferences', 'gear'], category: 'controls' }, + { id: 'refresh', paths: P.refreshCw, label: 'Refresh', aliases: ['reload', 'sync', 'cycle'], category: 'controls' }, + { id: 'undo', paths: P.undo2, label: 'Undo', aliases: ['back', 'revert'], category: 'controls' }, + { id: 'trash', paths: P.trash2, label: 'Trash', aliases: ['delete', 'remove', 'bin'], category: 'controls' }, + { id: 'link', paths: P.link, label: 'Link', aliases: ['chain', 'connect', 'url'], category: 'controls' }, + { id: 'search', paths: P.search, label: 'Search', aliases: ['find', 'magnify', 'lookup'], category: 'controls' }, + { id: 'add', paths: P.plus, label: 'Add', aliases: ['plus', 'new', 'create'], category: 'controls' }, + { id: 'show', paths: P.eye, label: 'Show', aliases: ['view', 'visible', 'preview'], category: 'controls' }, + { id: 'lock', paths: P.lock, label: 'Lock', aliases: ['secure', 'private', 'closed'], category: 'controls' }, + { id: 'key', paths: P.keyRound, label: 'Key', aliases: ['credential', 'token', 'auth'], category: 'controls' }, + { id: 'tool', paths: P.wrench, label: 'Tool', aliases: ['wrench', 'fix', 'maintenance'], category: 'controls' }, + + // Status + { id: 'check', paths: P.check, label: 'Check', aliases: ['done', 'ok', 'tick'], category: 'status' }, + { id: 'ok', paths: P.circleCheck, label: 'OK', aliases: ['success', 'valid', 'good'], category: 'status' }, + { id: 'warning', paths: P.triangleAlert, label: 'Warning', aliases: ['caution', 'alert', 'attention'], category: 'status' }, + { id: 'help', paths: P.circleHelp, label: 'Help', aliases: ['question', 'unknown', 'about'], category: 'status' }, + { id: 'off', paths: P.circleOff, label: 'Disabled', aliases: ['disable', 'inactive', 'banned'], category: 'status' }, + { id: 'shield', paths: P.shield, label: 'Shield', aliases: ['secure', 'protect', 'guard'], category: 'status' }, + { id: 'target', paths: P.target, label: 'Target', aliases: ['goal', 'aim', 'focus'], category: 'status' }, + { id: 'pulse', paths: P.activity, label: 'Pulse', aliases: ['activity', 'live', 'heartbeat', 'metrics'], category: 'status' }, + { id: 'trend', paths: P.trendingUp, label: 'Trending', aliases: ['rising', 'up', 'graph'], category: 'status' }, + { id: 'battery', paths: P.batteryFull, label: 'Battery', aliases: ['power', 'charge', 'cell'], category: 'status' }, + + // Office + { id: 'calendar', paths: P.calendar, label: 'Calendar', aliases: ['date', 'schedule', 'event'], category: 'office' }, + { id: 'mail', paths: P.mail, label: 'Mail', aliases: ['email', 'envelope', 'message'], category: 'office' }, + { id: 'coffee', paths: P.coffee, label: 'Coffee', aliases: ['drink', 'cafe', 'break'], category: 'office' }, + { id: 'briefcase', paths: P.briefcase, label: 'Briefcase', aliases: ['work', 'business', 'job'], category: 'office' }, + { id: 'doc', paths: P.fileText, label: 'Document', aliases: ['file', 'paper', 'text'], category: 'office' }, + { id: 'checklist', paths: P.clipboardList, label: 'Checklist', aliases: ['list', 'tasks', 'todo'], category: 'office' }, + { id: 'hashtag', paths: P.hash, label: 'Hashtag', aliases: ['tag', 'number', 'channel'], category: 'office' }, + { id: 'clock', paths: P.clock, label: 'Clock', aliases: ['time', 'hour', 'minute'], category: 'office' }, ]; const _byId: Record = Object.fromEntries( diff --git a/server/src/ledgrab/static/js/core/icon-paths.ts b/server/src/ledgrab/static/js/core/icon-paths.ts index b28a4b9..ee12c74 100644 --- a/server/src/ledgrab/static/js/core/icon-paths.ts +++ b/server/src/ledgrab/static/js/core/icon-paths.ts @@ -143,3 +143,61 @@ export const easingIn = ''; export const easingOut = ''; export const easingInOut = ''; export const easingSine = ''; + +// ───────────────────────────────────────────────────────────── +// Card-icon picker expansion — additional Lucide icons for the +// custom card-icon selector. These are surfaced through +// device-icons.ts but don't have type-resolution roles. +// ───────────────────────────────────────────────────────────── + +// Weather +export const cloudRain = ''; +export const cloudSnow = ''; +export const cloudLightning = ''; +export const cloudFog = ''; +export const wind = ''; +export const snowflake = ''; +export const umbrella = ''; +export const sunrise = ''; +export const sunset = ''; + +// Nature +export const treeDeciduous = ''; +export const flower2 = ''; +export const mountain = ''; +export const waves = ''; +export const sprout = ''; +export const trees = ''; + +// Rooms (extended) +export const chefHat = ''; +export const bath = ''; +export const warehouse = ''; + +// Office +export const calendar = ''; +export const mail = ''; +export const coffee = ''; +export const briefcase = ''; + +// Media (extended) +export const video = ''; +export const disc = ''; +export const projector = ''; + +// Hardware (extended) +export const laptop = ''; +export const server = ''; +export const router = ''; +export const webcam = ''; +export const bot = ''; +export const watch = ''; +export const memoryStick = ''; + +// Lighting (extended) +export const lampCeiling = ''; +export const lampDesk = ''; +export const lampWallUp = ''; +export const flashlight = ''; +export const lightbulbOff = ''; +export const candle = ''; diff --git a/server/src/ledgrab/static/locales/en.json b/server/src/ledgrab/static/locales/en.json index e354ddc..0cc7169 100644 --- a/server/src/ledgrab/static/locales/en.json +++ b/server/src/ledgrab/static/locales/en.json @@ -582,6 +582,87 @@ "device.icon.cat.media": "Media", "device.icon.cat.signal": "Signal", "device.icon.cat.ambience": "Ambience", + "device.icon.cat.weather": "Weather", + "device.icon.cat.nature": "Nature", + "device.icon.cat.controls": "Controls", + "device.icon.cat.status": "Status", + "device.icon.cat.office": "Office", + "device.icon.phone": "Phone", + "device.icon.package": "Device unit", + "device.icon.code": "Code", + "device.icon.laptop": "Laptop", + "device.icon.server": "Server", + "device.icon.router": "Router", + "device.icon.webcam": "Webcam", + "device.icon.bot": "Bot", + "device.icon.watch": "Smartwatch", + "device.icon.mcu": "Microcontroller", + "device.icon.dim": "Dim light", + "device.icon.ring": "Ring light", + "device.icon.point": "Point light", + "device.icon.ceiling": "Ceiling light", + "device.icon.desk_lamp": "Desk lamp", + "device.icon.wall_light": "Wall light", + "device.icon.flashlight": "Flashlight", + "device.icon.bulb_off": "Bulb off", + "device.icon.candle": "Candle", + "device.icon.kitchen": "Kitchen", + "device.icon.bath": "Bathroom", + "device.icon.garage": "Garage", + "device.icon.outdoor": "Outdoor", + "device.icon.projector": "Projector", + "device.icon.camcorder": "Camcorder", + "device.icon.disc": "Disc", + "device.icon.image": "Image", + "device.icon.audio_file": "Audio file", + "device.icon.send": "Send", + "device.icon.rain": "Rain", + "device.icon.snow": "Snow", + "device.icon.thunder": "Thunder", + "device.icon.fog": "Fog", + "device.icon.wind": "Wind", + "device.icon.snowflake": "Snowflake", + "device.icon.umbrella": "Umbrella", + "device.icon.sunrise": "Sunrise", + "device.icon.sunset": "Sunset", + "device.icon.tree": "Tree", + "device.icon.flower": "Flower", + "device.icon.mountain": "Mountain", + "device.icon.waves": "Waves", + "device.icon.sprout": "Sprout", + "device.icon.water_drops": "Water drops", + "device.icon.leaf": "Leaf", + "device.icon.switch": "Switch", + "device.icon.slider": "Slider", + "device.icon.settings": "Settings", + "device.icon.refresh": "Refresh", + "device.icon.undo": "Undo", + "device.icon.trash": "Trash", + "device.icon.link": "Link", + "device.icon.search": "Search", + "device.icon.add": "Add", + "device.icon.show": "Show", + "device.icon.lock": "Lock", + "device.icon.key": "Key", + "device.icon.tool": "Tool", + "device.icon.check": "Check", + "device.icon.ok": "OK", + "device.icon.warning": "Warning", + "device.icon.help": "Help", + "device.icon.off": "Disabled", + "device.icon.shield": "Shield", + "device.icon.target": "Target", + "device.icon.pulse": "Pulse", + "device.icon.trend": "Trending", + "device.icon.battery": "Battery", + "device.icon.calendar": "Calendar", + "device.icon.mail": "Mail", + "device.icon.coffee": "Coffee", + "device.icon.briefcase": "Briefcase", + "device.icon.doc": "Document", + "device.icon.checklist": "Checklist", + "device.icon.hashtag": "Hashtag", + "device.icon.clock": "Clock", "device.icon.entity.device": "Device", "device.icon.entity.target": "LED target", "device.icon.entity.ha_light_target": "HA light target", diff --git a/server/src/ledgrab/static/locales/ru.json b/server/src/ledgrab/static/locales/ru.json index 26f6fda..661472c 100644 --- a/server/src/ledgrab/static/locales/ru.json +++ b/server/src/ledgrab/static/locales/ru.json @@ -600,6 +600,87 @@ "device.icon.cat.media": "Медиа", "device.icon.cat.signal": "Сигнал", "device.icon.cat.ambience": "Атмосфера", + "device.icon.cat.weather": "Погода", + "device.icon.cat.nature": "Природа", + "device.icon.cat.controls": "Управление", + "device.icon.cat.status": "Состояние", + "device.icon.cat.office": "Офис", + "device.icon.phone": "Телефон", + "device.icon.package": "Устройство", + "device.icon.code": "Код", + "device.icon.laptop": "Ноутбук", + "device.icon.server": "Сервер", + "device.icon.router": "Маршрутизатор", + "device.icon.webcam": "Веб-камера", + "device.icon.bot": "Бот", + "device.icon.watch": "Умные часы", + "device.icon.mcu": "Микроконтроллер", + "device.icon.dim": "Приглушённый свет", + "device.icon.ring": "Кольцевая лампа", + "device.icon.point": "Точечный свет", + "device.icon.ceiling": "Потолочный светильник", + "device.icon.desk_lamp": "Настольная лампа", + "device.icon.wall_light": "Настенный светильник", + "device.icon.flashlight": "Фонарик", + "device.icon.bulb_off": "Лампа выключена", + "device.icon.candle": "Свеча", + "device.icon.kitchen": "Кухня", + "device.icon.bath": "Ванная", + "device.icon.garage": "Гараж", + "device.icon.outdoor": "Улица", + "device.icon.projector": "Проектор", + "device.icon.camcorder": "Видеокамера", + "device.icon.disc": "Диск", + "device.icon.image": "Изображение", + "device.icon.audio_file": "Аудиофайл", + "device.icon.send": "Отправить", + "device.icon.rain": "Дождь", + "device.icon.snow": "Снег", + "device.icon.thunder": "Гроза", + "device.icon.fog": "Туман", + "device.icon.wind": "Ветер", + "device.icon.snowflake": "Снежинка", + "device.icon.umbrella": "Зонт", + "device.icon.sunrise": "Восход", + "device.icon.sunset": "Закат", + "device.icon.tree": "Дерево", + "device.icon.flower": "Цветок", + "device.icon.mountain": "Гора", + "device.icon.waves": "Волны", + "device.icon.sprout": "Росток", + "device.icon.water_drops": "Капли воды", + "device.icon.leaf": "Лист", + "device.icon.switch": "Переключатель", + "device.icon.slider": "Слайдер", + "device.icon.settings": "Настройки", + "device.icon.refresh": "Обновить", + "device.icon.undo": "Отменить", + "device.icon.trash": "Корзина", + "device.icon.link": "Ссылка", + "device.icon.search": "Поиск", + "device.icon.add": "Добавить", + "device.icon.show": "Показать", + "device.icon.lock": "Замок", + "device.icon.key": "Ключ", + "device.icon.tool": "Инструмент", + "device.icon.check": "Галочка", + "device.icon.ok": "ОК", + "device.icon.warning": "Внимание", + "device.icon.help": "Справка", + "device.icon.off": "Отключено", + "device.icon.shield": "Щит", + "device.icon.target": "Цель", + "device.icon.pulse": "Пульс", + "device.icon.trend": "Тренд", + "device.icon.battery": "Батарея", + "device.icon.calendar": "Календарь", + "device.icon.mail": "Почта", + "device.icon.coffee": "Кофе", + "device.icon.briefcase": "Портфель", + "device.icon.doc": "Документ", + "device.icon.checklist": "Список", + "device.icon.hashtag": "Хэштег", + "device.icon.clock": "Часы", "device.icon.entity.device": "Устройство", "device.icon.entity.target": "LED-цель", "device.icon.entity.ha_light_target": "HA-светильник", diff --git a/server/src/ledgrab/static/locales/zh.json b/server/src/ledgrab/static/locales/zh.json index c5da76c..70662cd 100644 --- a/server/src/ledgrab/static/locales/zh.json +++ b/server/src/ledgrab/static/locales/zh.json @@ -600,6 +600,87 @@ "device.icon.cat.media": "媒体", "device.icon.cat.signal": "信号", "device.icon.cat.ambience": "氛围", + "device.icon.cat.weather": "天气", + "device.icon.cat.nature": "自然", + "device.icon.cat.controls": "控件", + "device.icon.cat.status": "状态", + "device.icon.cat.office": "办公", + "device.icon.phone": "手机", + "device.icon.package": "设备模块", + "device.icon.code": "代码", + "device.icon.laptop": "笔记本电脑", + "device.icon.server": "服务器", + "device.icon.router": "路由器", + "device.icon.webcam": "网络摄像头", + "device.icon.bot": "机器人", + "device.icon.watch": "智能手表", + "device.icon.mcu": "微控制器", + "device.icon.dim": "柔光", + "device.icon.ring": "环形灯", + "device.icon.point": "点光源", + "device.icon.ceiling": "吸顶灯", + "device.icon.desk_lamp": "台灯", + "device.icon.wall_light": "壁灯", + "device.icon.flashlight": "手电筒", + "device.icon.bulb_off": "灯泡关闭", + "device.icon.candle": "蜡烛", + "device.icon.kitchen": "厨房", + "device.icon.bath": "浴室", + "device.icon.garage": "车库", + "device.icon.outdoor": "户外", + "device.icon.projector": "投影仪", + "device.icon.camcorder": "摄像机", + "device.icon.disc": "光盘", + "device.icon.image": "图片", + "device.icon.audio_file": "音频文件", + "device.icon.send": "发送", + "device.icon.rain": "雨", + "device.icon.snow": "雪", + "device.icon.thunder": "雷电", + "device.icon.fog": "雾", + "device.icon.wind": "风", + "device.icon.snowflake": "雪花", + "device.icon.umbrella": "雨伞", + "device.icon.sunrise": "日出", + "device.icon.sunset": "日落", + "device.icon.tree": "树", + "device.icon.flower": "花", + "device.icon.mountain": "山", + "device.icon.waves": "波浪", + "device.icon.sprout": "嫩芽", + "device.icon.water_drops": "水滴", + "device.icon.leaf": "叶子", + "device.icon.switch": "开关", + "device.icon.slider": "滑块", + "device.icon.settings": "设置", + "device.icon.refresh": "刷新", + "device.icon.undo": "撤销", + "device.icon.trash": "回收站", + "device.icon.link": "链接", + "device.icon.search": "搜索", + "device.icon.add": "添加", + "device.icon.show": "显示", + "device.icon.lock": "锁定", + "device.icon.key": "钥匙", + "device.icon.tool": "工具", + "device.icon.check": "勾选", + "device.icon.ok": "正常", + "device.icon.warning": "警告", + "device.icon.help": "帮助", + "device.icon.off": "已禁用", + "device.icon.shield": "护盾", + "device.icon.target": "目标", + "device.icon.pulse": "脉冲", + "device.icon.trend": "趋势", + "device.icon.battery": "电池", + "device.icon.calendar": "日历", + "device.icon.mail": "邮件", + "device.icon.coffee": "咖啡", + "device.icon.briefcase": "公文包", + "device.icon.doc": "文档", + "device.icon.checklist": "清单", + "device.icon.hashtag": "话题", + "device.icon.clock": "时钟", "device.icon.entity.device": "设备", "device.icon.entity.target": "LED 目标", "device.icon.entity.ha_light_target": "HA 灯目标",