Fork garbage_collection avec décalage jours fériés FR
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""Needed for pytest."""
|
||||
@@ -0,0 +1,372 @@
|
||||
"""Component to integrate with garbage_colection."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Dict
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.util.dt as dt_util
|
||||
import voluptuous as vol
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_HIDDEN, CONF_ENTITIES, CONF_ENTITY_ID, WEEKDAYS
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from . import const, helpers
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
months = [m["value"] for m in const.MONTH_OPTIONS]
|
||||
frequencies = [f["value"] for f in const.FREQUENCY_OPTIONS]
|
||||
|
||||
SENSOR_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(const.CONF_FREQUENCY): vol.In(frequencies),
|
||||
vol.Optional(const.CONF_ICON_NORMAL): cv.icon,
|
||||
vol.Optional(const.CONF_ICON_TODAY): cv.icon,
|
||||
vol.Optional(const.CONF_ICON_TOMORROW): cv.icon,
|
||||
vol.Optional(const.CONF_EXPIRE_AFTER): helpers.time_text,
|
||||
vol.Optional(const.CONF_VERBOSE_STATE): cv.boolean,
|
||||
vol.Optional(ATTR_HIDDEN): cv.boolean,
|
||||
vol.Optional(const.CONF_MANUAL): cv.boolean,
|
||||
vol.Optional(const.CONF_DATE): helpers.month_day_text,
|
||||
vol.Optional(CONF_ENTITIES): cv.entity_ids,
|
||||
vol.Optional(const.CONF_COLLECTION_DAYS): vol.All(
|
||||
cv.ensure_list, [vol.In(WEEKDAYS)]
|
||||
),
|
||||
vol.Optional(const.CONF_FIRST_MONTH): vol.In(months),
|
||||
vol.Optional(const.CONF_LAST_MONTH): vol.In(months),
|
||||
vol.Optional(const.CONF_WEEKDAY_ORDER_NUMBER): vol.All(
|
||||
cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(min=1, max=5))]
|
||||
),
|
||||
vol.Optional(const.CONF_WEEK_ORDER_NUMBER): vol.All(
|
||||
cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(min=1, max=5))]
|
||||
),
|
||||
vol.Optional(const.CONF_PERIOD): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=1000)
|
||||
),
|
||||
vol.Optional(const.CONF_FIRST_WEEK): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1, max=52)
|
||||
),
|
||||
vol.Optional(const.CONF_FIRST_DATE): cv.date,
|
||||
vol.Optional(const.CONF_VERBOSE_FORMAT): cv.string,
|
||||
vol.Optional(const.CONF_DATE_FORMAT): cv.string,
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
const.DOMAIN: vol.Schema(
|
||||
{vol.Optional(const.CONF_SENSORS): vol.All(cv.ensure_list, [SENSOR_SCHEMA])}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
COLLECT_NOW_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(const.ATTR_LAST_COLLECTION): cv.datetime,
|
||||
}
|
||||
)
|
||||
|
||||
UPDATE_STATE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
|
||||
}
|
||||
)
|
||||
|
||||
ADD_REMOVE_DATE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Required(const.CONF_DATE): cv.date,
|
||||
}
|
||||
)
|
||||
|
||||
OFFSET_DATE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Required(const.CONF_DATE): cv.date,
|
||||
vol.Required(const.CONF_OFFSET): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=-31, max=31)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool:
|
||||
"""Set up platform - register services, inicialize data structure."""
|
||||
|
||||
async def handle_add_date(call: ServiceCall) -> None:
|
||||
"""Handle the add_date service call."""
|
||||
entity_ids = call.data.get(CONF_ENTITY_ID, [])
|
||||
collection_date = call.data.get(const.CONF_DATE)
|
||||
for entity_id in entity_ids:
|
||||
_LOGGER.debug("called add_date %s from %s", collection_date, entity_id)
|
||||
try:
|
||||
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
|
||||
await entity.add_date(collection_date)
|
||||
except KeyError as err:
|
||||
_LOGGER.error(
|
||||
"Failed adding date %s to %s (%s)",
|
||||
collection_date,
|
||||
entity_id,
|
||||
err,
|
||||
)
|
||||
|
||||
async def handle_remove_date(call: ServiceCall) -> None:
|
||||
"""Handle the remove_date service call."""
|
||||
entity_ids = call.data.get(CONF_ENTITY_ID, [])
|
||||
collection_date = call.data.get(const.CONF_DATE)
|
||||
for entity_id in entity_ids:
|
||||
_LOGGER.debug("called remove_date %s from %s", collection_date, entity_id)
|
||||
try:
|
||||
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
|
||||
await entity.remove_date(collection_date)
|
||||
except KeyError as err:
|
||||
_LOGGER.error(
|
||||
"Failed removing date %s from %s (%s)",
|
||||
collection_date,
|
||||
entity_id,
|
||||
err,
|
||||
)
|
||||
|
||||
async def handle_offset_date(call: ServiceCall) -> None:
|
||||
"""Handle the offset_date service call."""
|
||||
entity_ids = call.data.get(CONF_ENTITY_ID, [])
|
||||
offset = call.data.get(const.CONF_OFFSET)
|
||||
collection_date = call.data.get(const.CONF_DATE)
|
||||
for entity_id in entity_ids:
|
||||
_LOGGER.debug(
|
||||
"called offset_date %s by %d days for %s",
|
||||
collection_date,
|
||||
offset,
|
||||
entity_id,
|
||||
)
|
||||
try:
|
||||
new_date = collection_date + relativedelta(
|
||||
days=offset
|
||||
) # pyright: reportOptionalOperand=false
|
||||
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
|
||||
await asyncio.gather(
|
||||
entity.remove_date(collection_date), entity.add_date(new_date)
|
||||
)
|
||||
except (TypeError, KeyError) as err:
|
||||
_LOGGER.error("Failed ofsetting date for %s - %s", entity_id, err)
|
||||
break
|
||||
|
||||
async def handle_update_state(call: ServiceCall) -> None:
|
||||
"""Handle the update_state service call."""
|
||||
entity_ids = call.data.get(CONF_ENTITY_ID, [])
|
||||
for entity_id in entity_ids:
|
||||
_LOGGER.debug("called update_state for %s", entity_id)
|
||||
try:
|
||||
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
|
||||
entity.update_state()
|
||||
except KeyError as err:
|
||||
_LOGGER.error("Failed updating state for %s - %s", entity_id, err)
|
||||
|
||||
async def handle_collect_garbage(call: ServiceCall) -> None:
|
||||
"""Handle the collect_garbage service call."""
|
||||
entity_ids = call.data.get(CONF_ENTITY_ID, [])
|
||||
last_collection = call.data.get(const.ATTR_LAST_COLLECTION, helpers.now())
|
||||
for entity_id in entity_ids:
|
||||
_LOGGER.debug("called collect_garbage for %s", entity_id)
|
||||
try:
|
||||
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
|
||||
entity.last_collection = dt_util.as_local(last_collection)
|
||||
entity.update_state()
|
||||
except KeyError as err:
|
||||
_LOGGER.error(
|
||||
"Failed setting last collection for %s - %s", entity_id, err
|
||||
)
|
||||
|
||||
hass.data.setdefault(const.DOMAIN, {})
|
||||
hass.data[const.DOMAIN].setdefault(const.SENSOR_PLATFORM, {})
|
||||
hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
"collect_garbage",
|
||||
handle_collect_garbage,
|
||||
schema=COLLECT_NOW_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
"update_state",
|
||||
handle_update_state,
|
||||
schema=UPDATE_STATE_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
const.DOMAIN, "add_date", handle_add_date, schema=ADD_REMOVE_DATE_SCHEMA
|
||||
)
|
||||
hass.services.async_register(
|
||||
const.DOMAIN,
|
||||
"remove_date",
|
||||
handle_remove_date,
|
||||
schema=ADD_REMOVE_DATE_SCHEMA,
|
||||
)
|
||||
hass.services.async_register(
|
||||
const.DOMAIN, "offset_date", handle_offset_date, schema=OFFSET_DATE_SCHEMA
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Set up this integration using UI."""
|
||||
_LOGGER.debug(
|
||||
"Setting %s (%s) from ConfigFlow",
|
||||
config_entry.title,
|
||||
config_entry.options[const.CONF_FREQUENCY],
|
||||
)
|
||||
config_entry.add_update_listener(update_listener)
|
||||
# Add sensor
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(
|
||||
config_entry, const.SENSOR_PLATFORM
|
||||
)
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def async_remove_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
|
||||
"""Handle removal of an entry."""
|
||||
try:
|
||||
await hass.config_entries.async_forward_entry_unload(
|
||||
config_entry, const.SENSOR_PLATFORM
|
||||
)
|
||||
_LOGGER.info(
|
||||
"Successfully removed sensor from the garbage_collection integration"
|
||||
)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
async def async_migrate_entry(_: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Migrate old entry."""
|
||||
_LOGGER.info(
|
||||
"Migrating %s from version %s", config_entry.title, config_entry.version
|
||||
)
|
||||
new_data: Dict[str, Any] = {**config_entry.data}
|
||||
new_options: Dict[str, Any] = {**config_entry.options}
|
||||
removed_data: Dict[str, Any] = {}
|
||||
removed_options: Dict[str, Any] = {}
|
||||
_LOGGER.debug("new_data %s", new_data)
|
||||
_LOGGER.debug("new_options %s", new_options)
|
||||
if config_entry.version == 1:
|
||||
to_remove = [
|
||||
"offset",
|
||||
"move_country_holidays",
|
||||
"holiday_in_week_move",
|
||||
"holiday_pop_named",
|
||||
"holiday_move_offset",
|
||||
"prov",
|
||||
"state",
|
||||
"observed",
|
||||
"exclude_dates",
|
||||
"include_dates",
|
||||
]
|
||||
for remove in to_remove:
|
||||
if remove in new_data:
|
||||
removed_data[remove] = new_data[remove]
|
||||
del new_data[remove]
|
||||
if remove in new_options:
|
||||
removed_options[remove] = new_options[remove]
|
||||
del new_options[remove]
|
||||
if new_data.get(const.CONF_FREQUENCY) in const.MONTHLY_FREQUENCY:
|
||||
if const.CONF_WEEK_ORDER_NUMBER in new_data:
|
||||
new_data[const.CONF_WEEKDAY_ORDER_NUMBER] = new_data[
|
||||
const.CONF_WEEK_ORDER_NUMBER
|
||||
]
|
||||
new_data[const.CONF_FORCE_WEEK_NUMBERS] = True
|
||||
del new_data[const.CONF_WEEK_ORDER_NUMBER]
|
||||
else:
|
||||
new_data[const.CONF_FORCE_WEEK_NUMBERS] = False
|
||||
_LOGGER.info("Updated data config for week_order_number")
|
||||
if new_options.get(const.CONF_FREQUENCY) in const.MONTHLY_FREQUENCY:
|
||||
if const.CONF_WEEK_ORDER_NUMBER in new_options:
|
||||
new_options[const.CONF_WEEKDAY_ORDER_NUMBER] = new_options[
|
||||
const.CONF_WEEK_ORDER_NUMBER
|
||||
]
|
||||
new_options[const.CONF_FORCE_WEEK_NUMBERS] = True
|
||||
del new_options[const.CONF_WEEK_ORDER_NUMBER]
|
||||
_LOGGER.info("Updated options config for week_order_number")
|
||||
else:
|
||||
new_options[const.CONF_FORCE_WEEK_NUMBERS] = False
|
||||
if config_entry.version <= 4:
|
||||
if const.CONF_WEEKDAY_ORDER_NUMBER in new_data:
|
||||
new_data[const.CONF_WEEKDAY_ORDER_NUMBER] = list(
|
||||
map(str, new_data[const.CONF_WEEKDAY_ORDER_NUMBER])
|
||||
)
|
||||
if const.CONF_WEEKDAY_ORDER_NUMBER in new_options:
|
||||
new_options[const.CONF_WEEKDAY_ORDER_NUMBER] = list(
|
||||
map(str, new_options[const.CONF_WEEKDAY_ORDER_NUMBER])
|
||||
)
|
||||
if config_entry.version <= 5:
|
||||
for conf in [
|
||||
const.CONF_FREQUENCY,
|
||||
const.CONF_ICON_NORMAL,
|
||||
const.CONF_ICON_TODAY,
|
||||
const.CONF_ICON_TOMORROW,
|
||||
const.CONF_MANUAL,
|
||||
const.CONF_OFFSET,
|
||||
const.CONF_EXPIRE_AFTER,
|
||||
const.CONF_VERBOSE_STATE,
|
||||
const.CONF_FIRST_MONTH,
|
||||
const.CONF_LAST_MONTH,
|
||||
const.CONF_COLLECTION_DAYS,
|
||||
const.CONF_WEEKDAY_ORDER_NUMBER,
|
||||
const.CONF_FORCE_WEEK_NUMBERS,
|
||||
const.CONF_WEEK_ORDER_NUMBER,
|
||||
const.CONF_DATE,
|
||||
const.CONF_PERIOD,
|
||||
const.CONF_FIRST_WEEK,
|
||||
const.CONF_FIRST_DATE,
|
||||
const.CONF_SENSORS,
|
||||
const.CONF_VERBOSE_FORMAT,
|
||||
const.CONF_DATE_FORMAT,
|
||||
]:
|
||||
if conf in new_data:
|
||||
new_options[conf] = new_data.get(conf)
|
||||
del new_data[conf]
|
||||
if (
|
||||
const.CONF_EXPIRE_AFTER in new_options
|
||||
and len(new_options[const.CONF_EXPIRE_AFTER]) == 5
|
||||
):
|
||||
new_options[const.CONF_EXPIRE_AFTER] = (
|
||||
new_options[const.CONF_EXPIRE_AFTER] + ":00"
|
||||
)
|
||||
config_entry.version = const.CONFIG_VERSION
|
||||
config_entry.data = MappingProxyType({**new_data})
|
||||
config_entry.options = MappingProxyType({**new_options})
|
||||
if removed_data:
|
||||
_LOGGER.error(
|
||||
"Removed data config %s. "
|
||||
"Please check the documentation how to configure the functionality.",
|
||||
removed_data,
|
||||
)
|
||||
if removed_options:
|
||||
_LOGGER.error(
|
||||
"Removed options config %s. "
|
||||
"Please check the documentation how to configure the functionality.",
|
||||
removed_options,
|
||||
)
|
||||
_LOGGER.info(
|
||||
"%s migration to version %s successful",
|
||||
config_entry.title,
|
||||
config_entry.version,
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
"""Update listener - to re-create device after options update."""
|
||||
await hass.config_entries.async_forward_entry_unload(entry, const.SENSOR_PLATFORM)
|
||||
hass.async_add_job(
|
||||
hass.config_entries.async_forward_entry_setup(entry, const.SENSOR_PLATFORM)
|
||||
)
|
||||
@@ -0,0 +1,151 @@
|
||||
"""Garbage collection calendar."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from homeassistant.components.calendar import CalendarEntity, CalendarEvent
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from .const import CALENDAR_NAME, CALENDAR_PLATFORM, DOMAIN, SENSOR_PLATFORM
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
_: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
# pylint: disable=unused-argument
|
||||
"""Add calendar entity to HA."""
|
||||
async_add_entities([GarbageCollectionCalendar()], True)
|
||||
|
||||
|
||||
class GarbageCollectionCalendar(CalendarEntity):
|
||||
"""The garbage collection calendar class."""
|
||||
|
||||
instances = False
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Create empty calendar."""
|
||||
self._cal_data: dict = {}
|
||||
self._attr_name = CALENDAR_NAME
|
||||
GarbageCollectionCalendar.instances = True
|
||||
|
||||
@property
|
||||
def event(self) -> CalendarEvent | None:
|
||||
"""Return the next upcoming event."""
|
||||
return self.hass.data[DOMAIN][CALENDAR_PLATFORM].event
|
||||
|
||||
@property
|
||||
def name(self) -> str | None:
|
||||
"""Return the name of the entity."""
|
||||
return self._attr_name
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update all calendars."""
|
||||
await self.hass.data[DOMAIN][CALENDAR_PLATFORM].async_update()
|
||||
|
||||
async def async_get_events(
|
||||
self, hass: HomeAssistant, start_date: datetime, end_date: datetime
|
||||
) -> list[CalendarEvent]:
|
||||
"""Get all events in a specific time frame."""
|
||||
return await self.hass.data[DOMAIN][CALENDAR_PLATFORM].async_get_events(
|
||||
hass, start_date, end_date
|
||||
)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict | None:
|
||||
"""Return the device state attributes."""
|
||||
if self.hass.data[DOMAIN][CALENDAR_PLATFORM].event is None:
|
||||
# No tasks, we don't need to show anything.
|
||||
return None
|
||||
return {}
|
||||
|
||||
|
||||
class EntitiesCalendarData:
|
||||
"""Class used by the Entities Calendar class to hold all entity events."""
|
||||
|
||||
__slots__ = "_hass", "event", "entities", "_throttle"
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
"""Initialize an Entities Calendar Data."""
|
||||
self._hass = hass
|
||||
self.event: CalendarEvent | None = None
|
||||
self.entities: list[str] = []
|
||||
|
||||
def add_entity(self, entity_id: str) -> None:
|
||||
"""Append entity ID to the calendar."""
|
||||
if entity_id not in self.entities:
|
||||
self.entities.append(entity_id)
|
||||
|
||||
def remove_entity(self, entity_id: str) -> None:
|
||||
"""Remove entity ID from the calendar."""
|
||||
if entity_id in self.entities:
|
||||
self.entities.remove(entity_id)
|
||||
|
||||
async def async_get_events(
|
||||
self, hass: HomeAssistant, start_datetime: datetime, end_datetime: datetime
|
||||
) -> list[CalendarEvent]:
|
||||
"""Get all tasks in a specific time frame."""
|
||||
events: list[CalendarEvent] = []
|
||||
if SENSOR_PLATFORM not in hass.data[DOMAIN]:
|
||||
return events
|
||||
start_date = start_datetime.date()
|
||||
end_date = end_datetime.date()
|
||||
for entity in self.entities:
|
||||
if (
|
||||
entity not in hass.data[DOMAIN][SENSOR_PLATFORM]
|
||||
or hass.data[DOMAIN][SENSOR_PLATFORM][entity].hidden
|
||||
):
|
||||
continue
|
||||
garbage_collection = hass.data[DOMAIN][SENSOR_PLATFORM][entity]
|
||||
start = garbage_collection.get_next_date(start_date, True)
|
||||
while start is not None and start_date <= start <= end_date:
|
||||
try:
|
||||
end = start + timedelta(days=1)
|
||||
except TypeError:
|
||||
end = start
|
||||
name = (
|
||||
garbage_collection.name
|
||||
if garbage_collection.name is not None
|
||||
else "Unknown"
|
||||
)
|
||||
if garbage_collection.expire_after is None:
|
||||
event = CalendarEvent(
|
||||
summary=name,
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
else:
|
||||
event = CalendarEvent(
|
||||
summary=name,
|
||||
start=datetime.combine(start, datetime.min.time()),
|
||||
end=datetime.combine(start, garbage_collection.expire_after),
|
||||
)
|
||||
events.append(event)
|
||||
start = garbage_collection.get_next_date(
|
||||
start + timedelta(days=1), True
|
||||
)
|
||||
return events
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
async def async_update(self) -> None:
|
||||
"""Get the latest data."""
|
||||
next_dates = {}
|
||||
for entity in self.entities:
|
||||
if self._hass.data[DOMAIN][SENSOR_PLATFORM][entity].next_date is not None:
|
||||
next_dates[entity] = self._hass.data[DOMAIN][SENSOR_PLATFORM][
|
||||
entity
|
||||
].next_date
|
||||
if len(next_dates) > 0:
|
||||
entity_id = min(next_dates.keys(), key=(lambda k: next_dates[k]))
|
||||
start = next_dates[entity_id]
|
||||
end = start + timedelta(days=1)
|
||||
name = self._hass.data[DOMAIN][SENSOR_PLATFORM][entity_id].name
|
||||
self.event = CalendarEvent(
|
||||
summary=name,
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
@@ -0,0 +1,281 @@
|
||||
"""Adds config flow for GarbageCollection."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
# import uuid
|
||||
from collections.abc import Mapping
|
||||
from typing import Any, Dict, cast
|
||||
|
||||
import voluptuous as vol
|
||||
from homeassistant.const import ATTR_HIDDEN, CONF_ENTITIES, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import selector
|
||||
from homeassistant.helpers.schema_config_entry_flow import (
|
||||
SchemaConfigFlowHandler,
|
||||
SchemaFlowError,
|
||||
SchemaFlowFormStep,
|
||||
SchemaFlowMenuStep,
|
||||
SchemaOptionsFlowHandler,
|
||||
)
|
||||
|
||||
from . import const, helpers
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def _validate_config(
|
||||
_: SchemaConfigFlowHandler | SchemaOptionsFlowHandler, data: Any
|
||||
) -> Any:
|
||||
"""Validate config."""
|
||||
if const.CONF_DATE in data:
|
||||
try:
|
||||
helpers.month_day_text(data[const.CONF_DATE])
|
||||
except vol.Invalid as exc:
|
||||
raise SchemaFlowError("month_day") from exc
|
||||
return data
|
||||
|
||||
|
||||
def required(
|
||||
key: str, options: Dict[str, Any], default: Any | None = None
|
||||
) -> vol.Required:
|
||||
"""Return vol.Required."""
|
||||
if isinstance(options, dict) and key in options:
|
||||
suggested_value = options[key]
|
||||
elif default is not None:
|
||||
suggested_value = default
|
||||
else:
|
||||
return vol.Required(key)
|
||||
return vol.Required(key, description={"suggested_value": suggested_value})
|
||||
|
||||
|
||||
def optional(
|
||||
key: str, options: Dict[str, Any], default: Any | None = None
|
||||
) -> vol.Optional:
|
||||
"""Return vol.Optional."""
|
||||
if isinstance(options, dict) and key in options:
|
||||
suggested_value = options[key]
|
||||
elif default is not None:
|
||||
suggested_value = default
|
||||
else:
|
||||
return vol.Optional(key)
|
||||
return vol.Optional(key, description={"suggested_value": suggested_value})
|
||||
|
||||
|
||||
async def general_config_schema(
|
||||
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
|
||||
) -> vol.Schema:
|
||||
"""Generate config schema."""
|
||||
return vol.Schema(
|
||||
{
|
||||
optional(CONF_NAME, handler.options): selector.TextSelector(),
|
||||
required(
|
||||
const.CONF_FREQUENCY, handler.options, const.DEFAULT_FREQUENCY
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(options=const.FREQUENCY_OPTIONS)
|
||||
),
|
||||
optional(
|
||||
const.CONF_ICON_NORMAL, handler.options, const.DEFAULT_ICON_NORMAL
|
||||
): selector.IconSelector(),
|
||||
optional(
|
||||
const.CONF_ICON_TODAY, handler.options, const.DEFAULT_ICON_TODAY
|
||||
): selector.IconSelector(),
|
||||
optional(
|
||||
const.CONF_ICON_TOMORROW, handler.options, const.DEFAULT_ICON_TOMORROW
|
||||
): selector.IconSelector(),
|
||||
optional(const.CONF_EXPIRE_AFTER, handler.options): selector.TimeSelector(),
|
||||
optional(
|
||||
const.CONF_VERBOSE_STATE, handler.options, const.DEFAULT_VERBOSE_STATE
|
||||
): bool,
|
||||
optional(ATTR_HIDDEN, handler.options, False): bool,
|
||||
optional(const.CONF_MANUAL, handler.options, False): bool,
|
||||
optional(
|
||||
const.CONF_MOVE_COUNTRY_HOLIDAYS,
|
||||
handler.options,
|
||||
const.DEFAULT_HOLIDAY_IN_WEEK_MOVE,
|
||||
): bool,
|
||||
optional(
|
||||
const.CONF_HOLIDAY_COUNTRY,
|
||||
handler.options,
|
||||
const.DEFAULT_HOLIDAY_COUNTRY,
|
||||
): selector.TextSelector(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def general_options_schema(
|
||||
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
|
||||
) -> vol.Schema:
|
||||
"""Generate options schema."""
|
||||
return vol.Schema(
|
||||
{
|
||||
required(
|
||||
const.CONF_FREQUENCY, handler.options, const.DEFAULT_FREQUENCY
|
||||
): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(options=const.FREQUENCY_OPTIONS)
|
||||
),
|
||||
optional(
|
||||
const.CONF_ICON_NORMAL, handler.options, const.DEFAULT_ICON_NORMAL
|
||||
): selector.IconSelector(),
|
||||
optional(
|
||||
const.CONF_ICON_TODAY, handler.options, const.DEFAULT_ICON_TODAY
|
||||
): selector.IconSelector(),
|
||||
optional(
|
||||
const.CONF_ICON_TOMORROW, handler.options, const.DEFAULT_ICON_TOMORROW
|
||||
): selector.IconSelector(),
|
||||
optional(const.CONF_EXPIRE_AFTER, handler.options): selector.TimeSelector(),
|
||||
optional(
|
||||
const.CONF_VERBOSE_STATE, handler.options, const.DEFAULT_VERBOSE_STATE
|
||||
): bool,
|
||||
optional(ATTR_HIDDEN, handler.options, False): bool,
|
||||
optional(const.CONF_MANUAL, handler.options, False): bool,
|
||||
optional(
|
||||
const.CONF_MOVE_COUNTRY_HOLIDAYS,
|
||||
handler.options,
|
||||
const.DEFAULT_HOLIDAY_IN_WEEK_MOVE,
|
||||
): bool,
|
||||
optional(
|
||||
const.CONF_HOLIDAY_COUNTRY,
|
||||
handler.options,
|
||||
const.DEFAULT_HOLIDAY_COUNTRY,
|
||||
): selector.TextSelector(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def detail_config_schema(
|
||||
handler: SchemaConfigFlowHandler | SchemaOptionsFlowHandler,
|
||||
) -> vol.Schema:
|
||||
"""Generate options schema."""
|
||||
options_schema: Dict[vol.Optional | vol.Required, Any] = {}
|
||||
if handler.options[const.CONF_FREQUENCY] in const.ANNUAL_FREQUENCY:
|
||||
# "annual"
|
||||
options_schema[
|
||||
required(const.CONF_DATE, handler.options)
|
||||
] = selector.TextSelector()
|
||||
elif handler.options[const.CONF_FREQUENCY] in const.GROUP_FREQUENCY:
|
||||
# "group"
|
||||
options_schema[
|
||||
required(CONF_ENTITIES, handler.options)
|
||||
] = selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(
|
||||
domain="sensor", integration=const.DOMAIN, multiple=True
|
||||
),
|
||||
)
|
||||
elif handler.options[const.CONF_FREQUENCY] not in const.BLANK_FREQUENCY:
|
||||
# everything else except "blank" and every-n-days
|
||||
if handler.options[const.CONF_FREQUENCY] not in const.DAILY_FREQUENCY:
|
||||
options_schema[
|
||||
required(const.CONF_COLLECTION_DAYS, handler.options)
|
||||
] = selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=const.WEEKDAY_OPTIONS,
|
||||
multiple=True,
|
||||
mode=selector.SelectSelectorMode.LIST,
|
||||
)
|
||||
)
|
||||
# everything else except "blank"
|
||||
options_schema[
|
||||
optional(const.CONF_FIRST_MONTH, handler.options, const.DEFAULT_FIRST_MONTH)
|
||||
] = selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(options=const.MONTH_OPTIONS)
|
||||
)
|
||||
options_schema[
|
||||
optional(const.CONF_LAST_MONTH, handler.options, const.DEFAULT_LAST_MONTH)
|
||||
] = selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(options=const.MONTH_OPTIONS)
|
||||
)
|
||||
if handler.options[const.CONF_FREQUENCY] in const.MONTHLY_FREQUENCY:
|
||||
# "monthly"
|
||||
options_schema[
|
||||
optional(const.CONF_WEEKDAY_ORDER_NUMBER, handler.options)
|
||||
] = selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=const.ORDER_OPTIONS,
|
||||
multiple=True,
|
||||
mode=selector.SelectSelectorMode.LIST,
|
||||
)
|
||||
)
|
||||
options_schema[
|
||||
optional(const.CONF_FORCE_WEEK_NUMBERS, handler.options)
|
||||
] = selector.BooleanSelector()
|
||||
if handler.options[const.CONF_FREQUENCY] in const.WEEKLY_DAILY_MONTHLY:
|
||||
# "every-n-weeks", "every-n-days", "monthly"
|
||||
uom = {"every-n-weeks": "weeks", "every-n-days": "days", "monthly": "month"}
|
||||
options_schema[
|
||||
required(const.CONF_PERIOD, handler.options)
|
||||
] = selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
min=1,
|
||||
max=1000,
|
||||
mode=selector.NumberSelectorMode.BOX,
|
||||
unit_of_measurement=uom[handler.options[const.CONF_FREQUENCY]],
|
||||
)
|
||||
)
|
||||
if handler.options[const.CONF_FREQUENCY] in const.WEEKLY_FREQUENCY_X:
|
||||
# every-n-weeks
|
||||
options_schema[
|
||||
required(
|
||||
const.CONF_FIRST_WEEK, handler.options, const.DEFAULT_FIRST_WEEK
|
||||
)
|
||||
] = selector.NumberSelector(
|
||||
selector.NumberSelectorConfig(
|
||||
min=1,
|
||||
max=52,
|
||||
mode=selector.NumberSelectorMode.BOX,
|
||||
unit_of_measurement="weeks",
|
||||
)
|
||||
)
|
||||
if handler.options[const.CONF_FREQUENCY] in const.DAILY_FREQUENCY:
|
||||
# every-n-days
|
||||
options_schema[
|
||||
required(const.CONF_FIRST_DATE, handler.options, helpers.now().date())
|
||||
] = selector.DateSelector()
|
||||
if handler.options.get(const.CONF_VERBOSE_STATE, False):
|
||||
# "verbose_state"
|
||||
options_schema[
|
||||
required(
|
||||
const.CONF_VERBOSE_FORMAT, handler.options, const.DEFAULT_VERBOSE_FORMAT
|
||||
)
|
||||
] = selector.TextSelector()
|
||||
options_schema[
|
||||
required(const.CONF_DATE_FORMAT, handler.options, const.DEFAULT_DATE_FORMAT)
|
||||
] = selector.TextSelector()
|
||||
return vol.Schema(options_schema)
|
||||
|
||||
|
||||
async def choose_details_step(_: dict[str, Any]) -> str:
|
||||
"""Return next step_id for options flow."""
|
||||
return "detail"
|
||||
|
||||
|
||||
CONFIG_FLOW: Dict[str, SchemaFlowFormStep | SchemaFlowMenuStep] = {
|
||||
"user": SchemaFlowFormStep(general_config_schema, next_step=choose_details_step),
|
||||
"detail": SchemaFlowFormStep(
|
||||
detail_config_schema, validate_user_input=_validate_config
|
||||
),
|
||||
}
|
||||
OPTIONS_FLOW: Dict[str, SchemaFlowFormStep | SchemaFlowMenuStep] = {
|
||||
"init": SchemaFlowFormStep(general_options_schema, next_step=choose_details_step),
|
||||
"detail": SchemaFlowFormStep(
|
||||
detail_config_schema, validate_user_input=_validate_config
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# mypy: ignore-errors
|
||||
class GarbageCollectionConfigFlowHandler(SchemaConfigFlowHandler, domain=const.DOMAIN):
|
||||
"""Handle a config or options flow for GarbageCollection."""
|
||||
|
||||
config_flow = CONFIG_FLOW
|
||||
options_flow = OPTIONS_FLOW
|
||||
VERSION = const.CONFIG_VERSION
|
||||
|
||||
@callback
|
||||
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
|
||||
"""Return config entry title.
|
||||
|
||||
The options parameter contains config entry options, which is the union of user
|
||||
input from the config flow steps.
|
||||
"""
|
||||
return cast(str, options["name"]) if "name" in options else ""
|
||||
@@ -0,0 +1,144 @@
|
||||
"""Define constants used in garbage_collection."""
|
||||
from homeassistant.helpers import selector
|
||||
|
||||
# Constants for garbage_collection.
|
||||
# Base component constants
|
||||
DOMAIN = "garbage_collection"
|
||||
CALENDAR_NAME = "Garbage Collection"
|
||||
SENSOR_PLATFORM = "sensor"
|
||||
CALENDAR_PLATFORM = "calendar"
|
||||
ATTRIBUTION = "Data from this is provided by garbage_collection."
|
||||
CONFIG_VERSION = 6
|
||||
|
||||
ATTR_NEXT_DATE = "next_date"
|
||||
ATTR_DAYS = "days"
|
||||
ATTR_LAST_COLLECTION = "last_collection"
|
||||
ATTR_LAST_UPDATED = "last_updated"
|
||||
|
||||
# Device classes
|
||||
BINARY_SENSOR_DEVICE_CLASS = "connectivity"
|
||||
DEVICE_CLASS = "garbage_collection__schedule"
|
||||
|
||||
# Configuration
|
||||
CONF_SENSOR = "sensor"
|
||||
CONF_ENABLED = "enabled"
|
||||
CONF_FREQUENCY = "frequency"
|
||||
CONF_MANUAL = "manual_update"
|
||||
CONF_ICON_NORMAL = "icon_normal"
|
||||
CONF_ICON_TODAY = "icon_today"
|
||||
CONF_ICON_TOMORROW = "icon_tomorrow"
|
||||
CONF_OFFSET = "offset"
|
||||
CONF_EXPIRE_AFTER = "expire_after"
|
||||
CONF_VERBOSE_STATE = "verbose_state"
|
||||
CONF_FIRST_MONTH = "first_month"
|
||||
CONF_LAST_MONTH = "last_month"
|
||||
CONF_COLLECTION_DAYS = "collection_days"
|
||||
CONF_WEEKDAY_ORDER_NUMBER = "weekday_order_number"
|
||||
CONF_FORCE_WEEK_NUMBERS = "force_week_order_numbers"
|
||||
CONF_WEEK_ORDER_NUMBER = "week_order_number" # Obsolete
|
||||
CONF_DATE = "date"
|
||||
CONF_PERIOD = "period"
|
||||
CONF_FIRST_WEEK = "first_week"
|
||||
CONF_FIRST_DATE = "first_date"
|
||||
CONF_SENSORS = "sensors"
|
||||
CONF_VERBOSE_FORMAT = "verbose_format"
|
||||
CONF_DATE_FORMAT = "date_format"
|
||||
CONF_MOVE_COUNTRY_HOLIDAYS = "move_country_holidays"
|
||||
CONF_HOLIDAY_COUNTRY = "holiday_country"
|
||||
|
||||
# Defaults
|
||||
DEFAULT_NAME = DOMAIN
|
||||
DEFAULT_FIRST_MONTH = "jan"
|
||||
DEFAULT_LAST_MONTH = "dec"
|
||||
DEFAULT_FREQUENCY = "weekly"
|
||||
DEFAULT_PERIOD = 1
|
||||
DEFAULT_FIRST_WEEK = 1
|
||||
DEFAULT_VERBOSE_STATE = False
|
||||
DEFAULT_HOLIDAY_IN_WEEK_MOVE = False
|
||||
DEFAULT_HOLIDAY_COUNTRY = "FR"
|
||||
DEFAULT_DATE_FORMAT = "%d-%b-%Y"
|
||||
DEFAULT_VERBOSE_FORMAT = "on {date}, in {days} days"
|
||||
|
||||
# Icons
|
||||
DEFAULT_ICON_NORMAL = "mdi:trash-can"
|
||||
DEFAULT_ICON_TODAY = "mdi:delete-restore"
|
||||
DEFAULT_ICON_TOMORROW = "mdi:delete-circle"
|
||||
ICON = DEFAULT_ICON_NORMAL
|
||||
|
||||
# States
|
||||
STATE_TODAY = "today"
|
||||
STATE_TOMORROW = "tomorrow"
|
||||
|
||||
FREQUENCY_OPTIONS = [
|
||||
selector.SelectOptionDict(value="weekly", label="weekly"),
|
||||
selector.SelectOptionDict(value="even-weeks", label="even-weeks"),
|
||||
selector.SelectOptionDict(value="odd-weeks", label="odd-weeks"),
|
||||
selector.SelectOptionDict(value="every-n-weeks", label="every-n-weeks"),
|
||||
selector.SelectOptionDict(value="every-n-days", label="every-n-days"),
|
||||
selector.SelectOptionDict(value="monthly", label="monthly"),
|
||||
selector.SelectOptionDict(value="annual", label="annual"),
|
||||
selector.SelectOptionDict(value="blank", label="blank"),
|
||||
selector.SelectOptionDict(value="group", label="group"),
|
||||
]
|
||||
|
||||
WEEKLY_FREQUENCY = ["weekly", "even-weeks", "odd-weeks"]
|
||||
EXCEPT_ANNUAL_GROUP = [
|
||||
"weekly",
|
||||
"even-weeks",
|
||||
"odd-weeks",
|
||||
"every-n-weeks",
|
||||
"every-n-days",
|
||||
"monthly",
|
||||
"blank",
|
||||
]
|
||||
EXCEPT_ANNUAL_GROUP_BLANK = [
|
||||
"weekly",
|
||||
"even-weeks",
|
||||
"odd-weeks",
|
||||
"every-n-weeks",
|
||||
"every-n-days",
|
||||
"monthly",
|
||||
]
|
||||
WEEKLY_DAILY_MONTHLY = ["every-n-weeks", "every-n-days", "monthly"]
|
||||
WEEKLY_FREQUENCY_X = ["every-n-weeks"]
|
||||
DAILY_FREQUENCY = ["every-n-days"]
|
||||
DAILY_BLANK_FREQUENCY = ["blank", "every-n-days"]
|
||||
MONTHLY_FREQUENCY = ["monthly"]
|
||||
ANNUAL_GROUP_FREQUENCY = ["annual", "group"]
|
||||
ANNUAL_FREQUENCY = ["annual"]
|
||||
GROUP_FREQUENCY = ["group"]
|
||||
BLANK_FREQUENCY = ["blank"]
|
||||
|
||||
WEEKDAY_OPTIONS = [
|
||||
selector.SelectOptionDict(value="mon", label="Monday"),
|
||||
selector.SelectOptionDict(value="tue", label="Tuesday"),
|
||||
selector.SelectOptionDict(value="wed", label="Wednesday"),
|
||||
selector.SelectOptionDict(value="thu", label="Thursday"),
|
||||
selector.SelectOptionDict(value="fri", label="Friday"),
|
||||
selector.SelectOptionDict(value="sat", label="Saturday"),
|
||||
selector.SelectOptionDict(value="sun", label="Sunday"),
|
||||
]
|
||||
|
||||
|
||||
MONTH_OPTIONS = [
|
||||
selector.SelectOptionDict(value="jan", label="January"),
|
||||
selector.SelectOptionDict(value="feb", label="February"),
|
||||
selector.SelectOptionDict(value="mar", label="March"),
|
||||
selector.SelectOptionDict(value="apr", label="April"),
|
||||
selector.SelectOptionDict(value="may", label="May"),
|
||||
selector.SelectOptionDict(value="jun", label="June"),
|
||||
selector.SelectOptionDict(value="jul", label="July"),
|
||||
selector.SelectOptionDict(value="aug", label="August"),
|
||||
selector.SelectOptionDict(value="sep", label="September"),
|
||||
selector.SelectOptionDict(value="oct", label="October"),
|
||||
selector.SelectOptionDict(value="nov", label="November"),
|
||||
selector.SelectOptionDict(value="dec", label="December"),
|
||||
]
|
||||
|
||||
ORDER_OPTIONS = [
|
||||
selector.SelectOptionDict(value="1", label="1st"),
|
||||
selector.SelectOptionDict(value="2", label="2nd"),
|
||||
selector.SelectOptionDict(value="3", label="3rd"),
|
||||
selector.SelectOptionDict(value="4", label="4th"),
|
||||
selector.SelectOptionDict(value="5", label="5th"),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Diagnostics support for Garbage Collection."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import const
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
) -> Dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
entities = hass.data[const.DOMAIN][const.SENSOR_PLATFORM]
|
||||
entity_data = [
|
||||
entities[entity]
|
||||
for entity in entities
|
||||
if entities[entity].unique_id == entry.data["unique_id"]
|
||||
][0]
|
||||
data = {
|
||||
"entity_id": entity_data.entity_id,
|
||||
"state": entity_data.state,
|
||||
"attributes": entity_data.extra_state_attributes,
|
||||
"config_entry": entry.as_dict(),
|
||||
}
|
||||
return data
|
||||
@@ -0,0 +1,67 @@
|
||||
"""Set of functions to handle date and text conversion."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
from typing import Any
|
||||
|
||||
import homeassistant.util.dt as dt_util
|
||||
import voluptuous as vol
|
||||
from dateutil.parser import ParserError, parse
|
||||
|
||||
|
||||
def now() -> datetime:
|
||||
"""Return current date and time. Needed for testing."""
|
||||
return dt_util.now()
|
||||
|
||||
|
||||
def to_date(day: Any) -> date:
|
||||
"""Convert datetime or text to date, if not already datetime.
|
||||
|
||||
Used for the first date for every_n_days (configured as text)
|
||||
"""
|
||||
if day is None:
|
||||
raise ValueError
|
||||
if isinstance(day, date):
|
||||
return day
|
||||
if isinstance(day, datetime):
|
||||
return day.date()
|
||||
return date.fromisoformat(day)
|
||||
|
||||
|
||||
def parse_datetime(text: str) -> datetime | None:
|
||||
"""Parse text to datetime object."""
|
||||
try:
|
||||
return parse(text)
|
||||
except (ParserError, TypeError):
|
||||
return None
|
||||
|
||||
|
||||
def dates_to_texts(dates: list[date]) -> list[str]:
|
||||
"""Convert list of dates to texts."""
|
||||
converted: list[str] = []
|
||||
for record in dates:
|
||||
try:
|
||||
converted.append(record.isoformat())
|
||||
except ValueError:
|
||||
continue
|
||||
return converted
|
||||
|
||||
|
||||
def time_text(value: Any) -> str:
|
||||
"""Have to store time as text - datetime is not JSON serialisable."""
|
||||
if value is None or value == "":
|
||||
return ""
|
||||
try:
|
||||
return datetime.strptime(value, "%H:%M").time().strftime("%H:%M")
|
||||
except ValueError as error:
|
||||
raise vol.Invalid(f"Invalid date: {value}") from error
|
||||
|
||||
|
||||
def month_day_text(value: Any) -> str:
|
||||
"""Validate format month/day."""
|
||||
if value is None or value == "":
|
||||
return ""
|
||||
try:
|
||||
return datetime.strptime(value, "%m/%d").date().strftime("%m/%d")
|
||||
except ValueError as error:
|
||||
raise vol.Invalid(f"Invalid date: {value}") from error
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"domain": "garbage_collection",
|
||||
"name": "Garbage Collection",
|
||||
"codeowners": [
|
||||
"@bruxy70"
|
||||
],
|
||||
"config_flow": true,
|
||||
"dependencies": [],
|
||||
"documentation": "https://github.com/bruxy70/Garbage-Collection/",
|
||||
"integration_type": "helper",
|
||||
"iot_class": "calculated",
|
||||
"issue_tracker": "https://github.com/bruxy70/Garbage-Collection/issues",
|
||||
"requirements": [
|
||||
"python-dateutil>=2.8.2",
|
||||
"holidays>=0.40"
|
||||
],
|
||||
"version": "3.21-morgane-fr"
|
||||
}
|
||||
@@ -0,0 +1,840 @@
|
||||
"""Sensor platform for garbage_collection."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import date, datetime, time, timedelta
|
||||
from typing import Any, Dict, Generator
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import holidays
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_HIDDEN,
|
||||
CONF_ENTITIES,
|
||||
CONF_NAME,
|
||||
WEEKDAYS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
from . import const, helpers
|
||||
from .calendar import EntitiesCalendarData
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
THROTTLE_INTERVAL = timedelta(seconds=60)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
_: HomeAssistant, config_entry: ConfigEntry, async_add_devices: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Create garbage collection entities defined in config_flow and add them to HA."""
|
||||
frequency = config_entry.options.get(const.CONF_FREQUENCY)
|
||||
name = (
|
||||
config_entry.title
|
||||
if config_entry.title is not None
|
||||
else config_entry.data.get(CONF_NAME)
|
||||
)
|
||||
_frequency_function = {
|
||||
"weekly": WeeklyCollection,
|
||||
"even-weeks": WeeklyCollection,
|
||||
"odd-weeks": WeeklyCollection,
|
||||
"every-n-weeks": WeeklyCollection,
|
||||
"every-n-days": DailyCollection,
|
||||
"monthly": MonthlyCollection,
|
||||
"annual": AnnualCollection,
|
||||
"group": GroupCollection,
|
||||
"blank": BlankCollection,
|
||||
}
|
||||
if frequency in _frequency_function:
|
||||
add_devices = _frequency_function[frequency]
|
||||
async_add_devices([add_devices(config_entry)], True)
|
||||
else:
|
||||
_LOGGER.error("(%s) Unknown frequency %s", name, frequency)
|
||||
raise ValueError
|
||||
|
||||
|
||||
class GarbageCollection(RestoreEntity):
|
||||
"""GarbageCollection Sensor class."""
|
||||
|
||||
__slots__ = (
|
||||
"_attr_icon",
|
||||
"_attr_name",
|
||||
"_attr_state",
|
||||
"_collection_dates",
|
||||
"_date_format",
|
||||
"_days",
|
||||
"_first_month",
|
||||
"_hidden",
|
||||
"_holiday_country",
|
||||
"_holidays_calendar",
|
||||
"_icon_normal",
|
||||
"_icon_today",
|
||||
"_icon_tomorrow",
|
||||
"_last_month",
|
||||
"_last_updated",
|
||||
"_manual",
|
||||
"_next_date",
|
||||
"_verbose_format",
|
||||
"_verbose_state",
|
||||
"config_entry",
|
||||
"expire_after",
|
||||
"last_collection",
|
||||
)
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read configuration and initialise class variables."""
|
||||
config = config_entry.options
|
||||
self.config_entry = config_entry
|
||||
self._attr_name = (
|
||||
config_entry.title
|
||||
if config_entry.title is not None
|
||||
else config.get(CONF_NAME)
|
||||
)
|
||||
self._hidden = config.get(ATTR_HIDDEN, False)
|
||||
self._manual = config.get(const.CONF_MANUAL)
|
||||
first_month = config.get(const.CONF_FIRST_MONTH, const.DEFAULT_FIRST_MONTH)
|
||||
months = [m["value"] for m in const.MONTH_OPTIONS]
|
||||
self._first_month: int = (
|
||||
months.index(first_month) + 1 if first_month in months else 1
|
||||
)
|
||||
last_month = config.get(const.CONF_LAST_MONTH, const.DEFAULT_LAST_MONTH)
|
||||
self._last_month: int = (
|
||||
months.index(last_month) + 1 if last_month in months else 12
|
||||
)
|
||||
self._verbose_state = config.get(const.CONF_VERBOSE_STATE)
|
||||
self._icon_normal = config.get(const.CONF_ICON_NORMAL)
|
||||
self._icon_today = config.get(const.CONF_ICON_TODAY)
|
||||
self._icon_tomorrow = config.get(const.CONF_ICON_TOMORROW)
|
||||
exp = config.get(const.CONF_EXPIRE_AFTER)
|
||||
self.expire_after: time | None = (
|
||||
None
|
||||
if (
|
||||
exp is None
|
||||
or datetime.strptime(exp, "%H:%M:%S").time() == time(0, 0, 0)
|
||||
)
|
||||
else datetime.strptime(exp, "%H:%M:%S").time()
|
||||
)
|
||||
self._date_format = config.get(
|
||||
const.CONF_DATE_FORMAT, const.DEFAULT_DATE_FORMAT
|
||||
)
|
||||
self._verbose_format = config.get(
|
||||
const.CONF_VERBOSE_FORMAT, const.DEFAULT_VERBOSE_FORMAT
|
||||
)
|
||||
self._holiday_country = config.get(
|
||||
const.CONF_HOLIDAY_COUNTRY, const.DEFAULT_HOLIDAY_COUNTRY
|
||||
)
|
||||
if config.get(const.CONF_MOVE_COUNTRY_HOLIDAYS, False):
|
||||
try:
|
||||
self._holidays_calendar = holidays.country_holidays(
|
||||
self._holiday_country
|
||||
)
|
||||
except NotImplementedError:
|
||||
_LOGGER.error(
|
||||
"(%s) Unknown country code for holidays: %s",
|
||||
self._attr_name,
|
||||
self._holiday_country,
|
||||
)
|
||||
self._holidays_calendar = None
|
||||
else:
|
||||
self._holidays_calendar = None
|
||||
self._collection_dates: list[date] = []
|
||||
self._next_date: date | None = None
|
||||
self._last_updated: datetime | None = None
|
||||
self.last_collection: datetime | None = None
|
||||
self._days: int | None = None
|
||||
self._attr_state = "" if bool(self._verbose_state) else 2
|
||||
self._attr_icon = self._icon_normal
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When sensor is added to hassio, add it to calendar."""
|
||||
await super().async_added_to_hass()
|
||||
self.hass.data[const.DOMAIN][const.SENSOR_PLATFORM][self.entity_id] = self
|
||||
|
||||
# Restore stored state
|
||||
if (state := await self.async_get_last_state()) is not None:
|
||||
self._last_updated = None # Unblock update - after options change
|
||||
self._attr_state = state.state
|
||||
self._days = (
|
||||
state.attributes[const.ATTR_DAYS]
|
||||
if const.ATTR_DAYS in state.attributes
|
||||
else None
|
||||
)
|
||||
next_date = (
|
||||
helpers.parse_datetime(state.attributes[const.ATTR_NEXT_DATE])
|
||||
if const.ATTR_NEXT_DATE in state.attributes
|
||||
else None
|
||||
)
|
||||
self._next_date = None if next_date is None else next_date.date()
|
||||
self.last_collection = (
|
||||
helpers.parse_datetime(state.attributes[const.ATTR_LAST_COLLECTION])
|
||||
if const.ATTR_LAST_COLLECTION in state.attributes
|
||||
else None
|
||||
)
|
||||
|
||||
# Create device
|
||||
device_registry = dr.async_get(self.hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=self.config_entry.entry_id,
|
||||
identifiers={(const.DOMAIN, self.unique_id)},
|
||||
name=self._attr_name,
|
||||
manufacturer="bruxy70",
|
||||
)
|
||||
|
||||
# Create or add to calendar
|
||||
if not self.hidden:
|
||||
if const.CALENDAR_PLATFORM not in self.hass.data[const.DOMAIN]:
|
||||
self.hass.data[const.DOMAIN][
|
||||
const.CALENDAR_PLATFORM
|
||||
] = EntitiesCalendarData(self.hass)
|
||||
_LOGGER.debug("Creating garbage_collection calendar")
|
||||
await self.hass.config_entries.async_forward_entry_setup(
|
||||
self.config_entry, const.CALENDAR_PLATFORM
|
||||
)
|
||||
|
||||
self.hass.data[const.DOMAIN][const.CALENDAR_PLATFORM].add_entity(
|
||||
self.entity_id
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""When sensor is added to hassio, remove it."""
|
||||
await super().async_will_remove_from_hass()
|
||||
del self.hass.data[const.DOMAIN][const.SENSOR_PLATFORM][self.entity_id]
|
||||
self.hass.data[const.DOMAIN][const.CALENDAR_PLATFORM].remove_entity(
|
||||
self.entity_id
|
||||
)
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique ID to use for this sensor."""
|
||||
if "unique_id" in self.config_entry.data: # From legacy config
|
||||
return self.config_entry.data["unique_id"]
|
||||
return self.config_entry.entry_id
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
"""Return device info."""
|
||||
return {
|
||||
"identifiers": {(const.DOMAIN, self.unique_id)},
|
||||
"name": self.config_entry.data.get("name"),
|
||||
"manufacturer": "bruxy70",
|
||||
}
|
||||
|
||||
@property
|
||||
def name(self) -> str | None:
|
||||
"""Return the name of the sensor."""
|
||||
return self._attr_name
|
||||
|
||||
@property
|
||||
def next_date(self) -> date | None:
|
||||
"""Return next date attribute."""
|
||||
return self._next_date
|
||||
|
||||
@property
|
||||
def hidden(self) -> bool:
|
||||
"""Return the hidden attribute."""
|
||||
return self._hidden
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return unit of measurement - None for numerical value."""
|
||||
return None
|
||||
|
||||
@property
|
||||
def native_value(self) -> object:
|
||||
"""Return the state of the sensor."""
|
||||
return self._attr_state
|
||||
|
||||
@property
|
||||
def last_updated(self) -> datetime | None:
|
||||
"""Return when the sensor was last updated."""
|
||||
return self._last_updated
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Return the entity icon."""
|
||||
return self._attr_icon
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
||||
"""Return the state attributes."""
|
||||
state_attr = {
|
||||
const.ATTR_DAYS: self._days,
|
||||
const.ATTR_LAST_COLLECTION: self.last_collection,
|
||||
const.ATTR_LAST_UPDATED: self._last_updated,
|
||||
const.ATTR_NEXT_DATE: None
|
||||
if self._next_date is None
|
||||
else datetime(
|
||||
self._next_date.year, self._next_date.month, self._next_date.day
|
||||
).astimezone(),
|
||||
# Needed for translations to work
|
||||
ATTR_DEVICE_CLASS: self.DEVICE_CLASS,
|
||||
}
|
||||
return state_attr
|
||||
|
||||
@property
|
||||
def DEVICE_CLASS(self) -> str: # pylint: disable=C0103
|
||||
"""Return the class of the sensor."""
|
||||
return const.DEVICE_CLASS
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return main sensor parameters."""
|
||||
return (
|
||||
f"{self.__class__.__name__}(name={self._attr_name}, "
|
||||
f"entity_id={self.entity_id}, "
|
||||
f"state={self.state}, "
|
||||
f"attributes={self.extra_state_attributes})"
|
||||
)
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Find the next possible date starting from day1.
|
||||
|
||||
Only based on calendar, not looking at include/exclude days.
|
||||
Must be implemented for each child class.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
async def _async_ready_for_update(self) -> bool:
|
||||
"""Check if the entity is ready for the update.
|
||||
|
||||
Skip the update if the sensor was updated today
|
||||
Except for the sensors with with next date today and after the expiration time
|
||||
"""
|
||||
current_date_time = helpers.now()
|
||||
today = current_date_time.date()
|
||||
try:
|
||||
ready_for_update = bool(self._last_updated.date() != today) # type: ignore
|
||||
except AttributeError:
|
||||
return True
|
||||
try:
|
||||
if self._next_date == today and (
|
||||
(
|
||||
isinstance(self.expire_after, time)
|
||||
and current_date_time.time() >= self.expire_after
|
||||
)
|
||||
or (
|
||||
isinstance(self.last_collection, datetime)
|
||||
and self.last_collection.date() == today
|
||||
)
|
||||
):
|
||||
return True
|
||||
except (AttributeError, TypeError):
|
||||
pass
|
||||
return ready_for_update
|
||||
|
||||
def date_inside(self, dat: date) -> bool:
|
||||
"""Check if the date is inside first and last date."""
|
||||
month = dat.month
|
||||
if self._first_month <= self._last_month:
|
||||
return bool(self._first_month <= month <= self._last_month)
|
||||
return bool(self._first_month <= month or month <= self._last_month)
|
||||
|
||||
def move_to_range(self, day: date) -> date:
|
||||
"""If the date is not in range, move to the range."""
|
||||
if not self.date_inside(day):
|
||||
year = day.year
|
||||
month = day.month
|
||||
months = [m["label"] for m in const.MONTH_OPTIONS]
|
||||
if self._first_month <= self._last_month < month:
|
||||
_LOGGER.debug(
|
||||
"(%s) %s outside the range, lookig from %s next year",
|
||||
self._attr_name,
|
||||
day,
|
||||
months[self._first_month - 1],
|
||||
)
|
||||
return date(year + 1, self._first_month, 1)
|
||||
_LOGGER.debug(
|
||||
"(%s) %s outside the range, searching from %s",
|
||||
self._attr_name,
|
||||
day,
|
||||
months[self._first_month - 1],
|
||||
)
|
||||
return date(year, self._first_month, 1)
|
||||
return day
|
||||
|
||||
def collection_schedule(
|
||||
self, date1: date | None = None, date2: date | None = None
|
||||
) -> Generator[date, None, None]:
|
||||
"""Get dates within configured date range."""
|
||||
today = helpers.now().date()
|
||||
first_date: date = date(today.year - 1, 1, 1) if date1 is None else date1
|
||||
last_date: date = date(today.year + 1, 12, 31) if date2 is None else date2
|
||||
first_date = self.move_to_range(first_date)
|
||||
while True:
|
||||
try:
|
||||
next_date = self._find_candidate_date(first_date)
|
||||
except (TypeError, ValueError):
|
||||
return
|
||||
if next_date is None or next_date > last_date:
|
||||
return
|
||||
if (new_date := self.move_to_range(next_date)) != next_date:
|
||||
first_date = new_date # continue from next year
|
||||
else:
|
||||
yield next_date
|
||||
first_date = next_date + relativedelta(days=1) # look from the next day
|
||||
|
||||
def _shift_for_holiday(self, collection_date: date) -> date:
|
||||
"""Move the date forward if a public holiday falls on it or earlier that week.
|
||||
|
||||
First check Monday..collection_date (inclusive) for a holiday: if any day in
|
||||
that range is a holiday, move forward by one day. Then keep moving forward,
|
||||
one day at a time, while the new candidate day is itself a holiday.
|
||||
"""
|
||||
if self._holidays_calendar is None:
|
||||
return collection_date
|
||||
monday = collection_date - timedelta(days=collection_date.weekday())
|
||||
week_has_holiday = any(
|
||||
(monday + timedelta(days=i)) in self._holidays_calendar
|
||||
for i in range(collection_date.weekday() + 1)
|
||||
)
|
||||
if not week_has_holiday:
|
||||
return collection_date
|
||||
shifted = collection_date + timedelta(days=1)
|
||||
while shifted in self._holidays_calendar:
|
||||
shifted = shifted + timedelta(days=1)
|
||||
_LOGGER.debug(
|
||||
"(%s) %s shifted to %s because of a public holiday",
|
||||
self._attr_name,
|
||||
collection_date,
|
||||
shifted,
|
||||
)
|
||||
return shifted
|
||||
|
||||
async def _async_load_collection_dates(self) -> None:
|
||||
"""Fill the collection dates list."""
|
||||
self._collection_dates.clear()
|
||||
for collection_date in self.collection_schedule():
|
||||
collection_date = self._shift_for_holiday(collection_date)
|
||||
if collection_date not in self._collection_dates:
|
||||
self._collection_dates.append(collection_date)
|
||||
self._collection_dates.sort()
|
||||
|
||||
async def add_date(self, collection_date: date) -> None:
|
||||
"""Add date to _collection_dates."""
|
||||
if collection_date not in self._collection_dates:
|
||||
self._collection_dates.append(collection_date)
|
||||
self._collection_dates.sort()
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s not added to %s - already on the collection schedule",
|
||||
collection_date,
|
||||
self.name,
|
||||
)
|
||||
|
||||
async def remove_date(self, collection_date: date) -> None:
|
||||
"""Remove date from _collection dates."""
|
||||
try:
|
||||
self._collection_dates.remove(collection_date)
|
||||
except ValueError:
|
||||
_LOGGER.warning(
|
||||
"%s not removed from %s - not in the collection schedule",
|
||||
collection_date,
|
||||
self.name,
|
||||
)
|
||||
|
||||
def get_next_date(self, first_date: date, ignore_today=False) -> date | None:
|
||||
"""Get next date from self._collection_dates."""
|
||||
current_date_time = helpers.now()
|
||||
for d in self._collection_dates: # pylint: disable=invalid-name
|
||||
if d < first_date:
|
||||
continue
|
||||
if not ignore_today and d == current_date_time.date():
|
||||
expiration = (
|
||||
self.expire_after
|
||||
if self.expire_after is not None
|
||||
else time(23, 59, 59)
|
||||
)
|
||||
if current_date_time.time() > expiration or (
|
||||
self.last_collection is not None
|
||||
and self.last_collection.date() == current_date_time.date()
|
||||
and current_date_time.time() >= self.last_collection.time()
|
||||
):
|
||||
continue
|
||||
return d
|
||||
return None
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Get the latest data and updates the states."""
|
||||
if not await self._async_ready_for_update() or not self.hass.is_running:
|
||||
return
|
||||
|
||||
_LOGGER.debug("(%s) Calling update", self._attr_name)
|
||||
await self._async_load_collection_dates()
|
||||
_LOGGER.debug(
|
||||
"(%s) Dates loaded, firing a garbage_collection_loaded event",
|
||||
self._attr_name,
|
||||
)
|
||||
event_data = {
|
||||
"entity_id": self.entity_id,
|
||||
"collection_dates": helpers.dates_to_texts(self._collection_dates),
|
||||
}
|
||||
self.hass.bus.async_fire("garbage_collection_loaded", event_data)
|
||||
if not self._manual:
|
||||
self.update_state()
|
||||
|
||||
def update_state(self) -> None:
|
||||
"""Pick the first event from collection dates, update attributes."""
|
||||
_LOGGER.debug("(%s) Looking for next collection", self._attr_name)
|
||||
self._last_updated = helpers.now()
|
||||
today = self._last_updated.date()
|
||||
self._next_date = self.get_next_date(today)
|
||||
if self._next_date is not None:
|
||||
_LOGGER.debug(
|
||||
"(%s) next_date (%s), today (%s)",
|
||||
self._attr_name,
|
||||
self._next_date,
|
||||
today,
|
||||
)
|
||||
self._days = (self._next_date - today).days
|
||||
next_date_txt = self._next_date.strftime(self._date_format)
|
||||
_LOGGER.debug(
|
||||
"(%s) Found next collection date: %s, that is in %d days",
|
||||
self._attr_name,
|
||||
next_date_txt,
|
||||
self._days,
|
||||
)
|
||||
if self._days > 1:
|
||||
if bool(self._verbose_state):
|
||||
self._attr_state = self._verbose_format.format(
|
||||
date=next_date_txt, days=self._days
|
||||
)
|
||||
# self._attr_state = "on_date"
|
||||
else:
|
||||
self._attr_state = 2
|
||||
self._attr_icon = self._icon_normal
|
||||
else:
|
||||
if self._days == 0:
|
||||
if bool(self._verbose_state):
|
||||
self._attr_state = const.STATE_TODAY
|
||||
else:
|
||||
self._attr_state = self._days
|
||||
self._attr_icon = self._icon_today
|
||||
elif self._days == 1:
|
||||
if bool(self._verbose_state):
|
||||
self._attr_state = const.STATE_TOMORROW
|
||||
else:
|
||||
self._attr_state = self._days
|
||||
self._attr_icon = self._icon_tomorrow
|
||||
else:
|
||||
self._days = None
|
||||
self._attr_state = None
|
||||
self._attr_icon = self._icon_normal
|
||||
|
||||
|
||||
class WeeklyCollection(GarbageCollection):
|
||||
"""Collection every n weeks, odd weeks or even weeks."""
|
||||
|
||||
__slots__ = "_collection_days", "_first_week", "_period"
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read parameters specific for Weekly Collection Frequency."""
|
||||
super().__init__(config_entry)
|
||||
config = config_entry.options
|
||||
self._collection_days = config.get(const.CONF_COLLECTION_DAYS, [])
|
||||
self._period: int
|
||||
self._first_week: int
|
||||
frequency = config.get(const.CONF_FREQUENCY)
|
||||
if frequency == "weekly":
|
||||
self._period = 1
|
||||
self._first_week = 1
|
||||
elif frequency == "even-weeks":
|
||||
self._period = 2
|
||||
self._first_week = 2
|
||||
elif frequency == "odd-weeks":
|
||||
self._period = 2
|
||||
self._first_week = 1
|
||||
else:
|
||||
self._period = config.get(const.CONF_PERIOD, 1)
|
||||
self._first_week = config.get(const.CONF_FIRST_WEEK, 1)
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Calculate possible date, for weekly frequency."""
|
||||
week = day1.isocalendar()[1]
|
||||
weekday = day1.weekday()
|
||||
offset = -1
|
||||
if (week - self._first_week) % self._period == 0: # Collection this week
|
||||
for day_name in self._collection_days:
|
||||
day_index = WEEKDAYS.index(day_name)
|
||||
if day_index >= weekday: # Collection still did not happen
|
||||
offset = day_index - weekday
|
||||
break
|
||||
iterate_by_week = 7 - weekday + WEEKDAYS.index(self._collection_days[0])
|
||||
while offset == -1: # look in following weeks
|
||||
candidate = day1 + relativedelta(days=iterate_by_week)
|
||||
week = candidate.isocalendar()[1]
|
||||
if (week - self._first_week) % self._period == 0:
|
||||
offset = iterate_by_week
|
||||
break
|
||||
iterate_by_week += 7
|
||||
return day1 + relativedelta(days=offset)
|
||||
|
||||
|
||||
class DailyCollection(GarbageCollection):
|
||||
"""Collection every n days."""
|
||||
|
||||
__slots__ = "_first_date", "_period"
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read parameters specific for Daily Collection Frequency."""
|
||||
super().__init__(config_entry)
|
||||
config = config_entry.options
|
||||
self._period = config.get(const.CONF_PERIOD)
|
||||
self._first_date: date | None
|
||||
try:
|
||||
self._first_date = helpers.to_date(config.get(const.CONF_FIRST_DATE))
|
||||
except ValueError:
|
||||
self._first_date = None
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Calculate possible date, for every-n-days frequency."""
|
||||
try:
|
||||
if (day1 - self._first_date).days % self._period == 0: # type: ignore
|
||||
return day1
|
||||
offset = self._period - (
|
||||
(day1 - self._first_date).days % self._period # type: ignore
|
||||
)
|
||||
except TypeError as error:
|
||||
raise ValueError(
|
||||
f"({self._attr_name}) Please configure first_date and period "
|
||||
"for every-n-days collection frequency."
|
||||
) from error
|
||||
return day1 + relativedelta(days=offset)
|
||||
|
||||
|
||||
class MonthlyCollection(GarbageCollection):
|
||||
"""Collection every nth weekday of each month."""
|
||||
|
||||
__slots__ = (
|
||||
"_collection_days",
|
||||
"_monthly_force_week_numbers",
|
||||
"_period",
|
||||
"_weekday_order_numbers",
|
||||
"_week_order_numbers",
|
||||
)
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read parameters specific for Monthly Collection Frequency."""
|
||||
super().__init__(config_entry)
|
||||
config = config_entry.options
|
||||
self._collection_days = config.get(const.CONF_COLLECTION_DAYS, [])
|
||||
self._monthly_force_week_numbers = config.get(
|
||||
const.CONF_FORCE_WEEK_NUMBERS, False
|
||||
)
|
||||
self._weekday_order_numbers: list
|
||||
self._week_order_numbers: list
|
||||
order_numbers: list = []
|
||||
if const.CONF_WEEKDAY_ORDER_NUMBER in config:
|
||||
order_numbers = list(map(int, config[const.CONF_WEEKDAY_ORDER_NUMBER]))
|
||||
if self._monthly_force_week_numbers:
|
||||
self._weekday_order_numbers = []
|
||||
self._week_order_numbers = order_numbers
|
||||
else:
|
||||
self._weekday_order_numbers = order_numbers
|
||||
self._week_order_numbers = []
|
||||
self._period = config.get(const.CONF_PERIOD, 1)
|
||||
|
||||
@staticmethod
|
||||
def nth_week_date(
|
||||
week_number: int, date_of_month: date, collection_day: int
|
||||
) -> date:
|
||||
"""Find weekday in the nth week of the month."""
|
||||
first_of_month = date(date_of_month.year, date_of_month.month, 1)
|
||||
return first_of_month + relativedelta(
|
||||
days=collection_day - first_of_month.weekday() + (week_number - 1) * 7
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def nth_weekday_date(
|
||||
weekday_number: int, date_of_month: date, collection_day: int
|
||||
) -> date:
|
||||
"""Find nth weekday of the month."""
|
||||
first_of_month = date(date_of_month.year, date_of_month.month, 1)
|
||||
# 1st of the month is before the day of collection
|
||||
# (so 1st collection week the week when month starts)
|
||||
if collection_day >= first_of_month.weekday():
|
||||
return first_of_month + relativedelta(
|
||||
days=collection_day
|
||||
- first_of_month.weekday()
|
||||
+ (weekday_number - 1) * 7
|
||||
)
|
||||
return first_of_month + relativedelta(
|
||||
days=7
|
||||
- first_of_month.weekday()
|
||||
+ collection_day
|
||||
+ (weekday_number - 1) * 7
|
||||
)
|
||||
|
||||
def _monthly_candidate(self, day1: date) -> date:
|
||||
"""Calculate possible date, for monthly frequency."""
|
||||
if self._monthly_force_week_numbers:
|
||||
for week_order_number in self._week_order_numbers:
|
||||
candidate_date = MonthlyCollection.nth_week_date(
|
||||
week_order_number, day1, WEEKDAYS.index(self._collection_days[0])
|
||||
)
|
||||
# date is today or in the future -> we have the date
|
||||
if candidate_date >= day1:
|
||||
return candidate_date
|
||||
else:
|
||||
for weekday_order_number in self._weekday_order_numbers:
|
||||
candidate_date = MonthlyCollection.nth_weekday_date(
|
||||
weekday_order_number,
|
||||
day1,
|
||||
WEEKDAYS.index(self._collection_days[0]),
|
||||
)
|
||||
# date is today or in the future -> we have the date
|
||||
if candidate_date >= day1:
|
||||
return candidate_date
|
||||
if day1.month == 12:
|
||||
next_collection_month = date(day1.year + 1, 1, 1)
|
||||
else:
|
||||
next_collection_month = date(day1.year, day1.month + 1, 1)
|
||||
if self._monthly_force_week_numbers:
|
||||
return MonthlyCollection.nth_week_date(
|
||||
self._week_order_numbers[0],
|
||||
next_collection_month,
|
||||
WEEKDAYS.index(self._collection_days[0]),
|
||||
)
|
||||
return MonthlyCollection.nth_weekday_date(
|
||||
self._weekday_order_numbers[0],
|
||||
next_collection_month,
|
||||
WEEKDAYS.index(self._collection_days[0]),
|
||||
)
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
if self._period is None or self._period == 1:
|
||||
return self._monthly_candidate(day1)
|
||||
else:
|
||||
candidate_date = self._monthly_candidate(day1)
|
||||
while (candidate_date.month - self._first_month) % self._period != 0:
|
||||
candidate_date = self._monthly_candidate(
|
||||
candidate_date + relativedelta(days=1)
|
||||
)
|
||||
return candidate_date
|
||||
|
||||
|
||||
class AnnualCollection(GarbageCollection):
|
||||
"""Collection every year."""
|
||||
|
||||
__slots__ = ("_date",)
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read parameters specific for Annual Collection Frequency."""
|
||||
super().__init__(config_entry)
|
||||
config = config_entry.options
|
||||
self._date = config.get(const.CONF_DATE)
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Calculate possible date, for annual frequency."""
|
||||
year = day1.year
|
||||
try:
|
||||
conf_date = datetime.strptime(self._date, "%m/%d").date()
|
||||
except TypeError as error:
|
||||
raise ValueError(
|
||||
f"({self._attr_name}) Please configure the date "
|
||||
"for annual collection frequency."
|
||||
) from error
|
||||
if (candidate_date := date(year, conf_date.month, conf_date.day)) < day1:
|
||||
candidate_date = date(year + 1, conf_date.month, conf_date.day)
|
||||
return candidate_date
|
||||
|
||||
|
||||
class GroupCollection(GarbageCollection):
|
||||
"""Group number of sensors."""
|
||||
|
||||
__slots__ = ("_entities",)
|
||||
|
||||
def __init__(self, config_entry: ConfigEntry) -> None:
|
||||
"""Read parameters specific for Group Collection Frequency."""
|
||||
super().__init__(config_entry)
|
||||
config = config_entry.options
|
||||
self._entities = config.get(CONF_ENTITIES, [])
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Calculate possible date, for group frequency."""
|
||||
candidate_date = None
|
||||
try:
|
||||
for entity_id in self._entities:
|
||||
entity: GarbageCollection = self.hass.data[const.DOMAIN][
|
||||
const.SENSOR_PLATFORM
|
||||
][entity_id]
|
||||
next_date = entity.get_next_date(day1)
|
||||
if next_date is not None and (
|
||||
candidate_date is None or next_date < candidate_date
|
||||
):
|
||||
candidate_date = next_date
|
||||
except KeyError as error:
|
||||
raise ValueError from error
|
||||
except TypeError as error:
|
||||
_LOGGER.error("(%s) Please add entities for the group.", self._attr_name)
|
||||
raise ValueError from error
|
||||
return candidate_date
|
||||
|
||||
async def _async_ready_for_update(self) -> bool:
|
||||
"""Check if the entity is ready for the update.
|
||||
|
||||
For group sensors wait for update of the sensors in the group
|
||||
"""
|
||||
current_date_time = helpers.now()
|
||||
today = current_date_time.date()
|
||||
try:
|
||||
ready_for_update = bool(self._last_updated.date() != today) # type: ignore
|
||||
except AttributeError:
|
||||
ready_for_update = True
|
||||
members_ready = True
|
||||
for entity_id in self._entities:
|
||||
try:
|
||||
entity: GarbageCollection = self.hass.data[const.DOMAIN][
|
||||
const.SENSOR_PLATFORM
|
||||
][entity_id]
|
||||
await entity.async_update()
|
||||
except KeyError:
|
||||
members_ready = False
|
||||
break
|
||||
if (last_updated := entity.last_updated) is None:
|
||||
ready_for_update = True
|
||||
continue
|
||||
# Wait for all members to get updated
|
||||
if last_updated.date() != today:
|
||||
members_ready = False
|
||||
break
|
||||
# A member got updated after the group update
|
||||
if self._last_updated is None or last_updated > self._last_updated:
|
||||
ready_for_update = True
|
||||
if ready_for_update and not members_ready:
|
||||
ready_for_update = False
|
||||
return ready_for_update
|
||||
|
||||
|
||||
class BlankCollection(GarbageCollection):
|
||||
"""No collection - for mnual update."""
|
||||
|
||||
def _find_candidate_date(self, day1: date) -> date | None:
|
||||
"""Do not return any date for blank frequency."""
|
||||
return None
|
||||
|
||||
async def _async_load_collection_dates(self) -> None:
|
||||
"""Clear collection dates (filled in by the blueprint)."""
|
||||
self._collection_dates.clear()
|
||||
return
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Get the latest data and updates the states."""
|
||||
if not await self._async_ready_for_update() or not self.hass.is_running:
|
||||
return
|
||||
|
||||
_LOGGER.debug("(%s) Calling update", self._attr_name)
|
||||
await self._async_load_collection_dates()
|
||||
_LOGGER.debug(
|
||||
"(%s) Dates loaded, firing a garbage_collection_loaded event",
|
||||
self._attr_name,
|
||||
)
|
||||
event_data = {
|
||||
"entity_id": self.entity_id,
|
||||
"collection_dates": [],
|
||||
}
|
||||
self.hass.bus.async_fire("garbage_collection_loaded", event_data)
|
||||
@@ -0,0 +1,60 @@
|
||||
collect_garbage:
|
||||
description: Set the last_collection attribute to the current date and time.
|
||||
target:
|
||||
entity:
|
||||
integration: garbage_collection
|
||||
fields:
|
||||
entity_id:
|
||||
description: The garbage_collection sensor entity_id
|
||||
example: sensor.general_waste
|
||||
last_collection:
|
||||
description: Date and time of the last collection (optional)
|
||||
example: "2020-08-16 10:54:00"
|
||||
add_date:
|
||||
description: Manually add collection date.
|
||||
target:
|
||||
entity:
|
||||
integration: garbage_collection
|
||||
fields:
|
||||
entity_id:
|
||||
description: The garbage_collection sensor entity_id
|
||||
example: sensor.general_waste
|
||||
date:
|
||||
description: Collection date to add
|
||||
example: '"2020-08-16"'
|
||||
offset_date:
|
||||
description: Move the collection date by a number of days.
|
||||
target:
|
||||
entity:
|
||||
integration: garbage_collection
|
||||
fields:
|
||||
entity_id:
|
||||
description: The garbage_collection sensor entity_id
|
||||
example: sensor.general_waste
|
||||
date:
|
||||
description: Collection date to move
|
||||
example: '"2020-08-16"'
|
||||
offset:
|
||||
description: Nuber of days to move (negative number will move it back)
|
||||
example: 1
|
||||
remove_date:
|
||||
description: Remove automatically calculated collection date.
|
||||
target:
|
||||
entity:
|
||||
integration: garbage_collection
|
||||
fields:
|
||||
entity_id:
|
||||
description: The garbage_collection sensor entity_id
|
||||
example: sensor.general_waste
|
||||
date:
|
||||
description: Collection date to remove
|
||||
example: '"2020-08-16"'
|
||||
update_state:
|
||||
description: Update the entity state and attributes. Used with the manual_update option, do defer the update after changing the automatically created schedule by automation trigered by the garbage_collection_loaded event.
|
||||
target:
|
||||
entity:
|
||||
integration: garbage_collection
|
||||
fields:
|
||||
entity_id:
|
||||
description: The garbage_collection sensor entity_id
|
||||
example: sensor.general_waste
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Garbage Collection - Konfigurace (1/2)",
|
||||
"description": "Zadej jméno sensoru a nastav parametry. Více na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Friendly name",
|
||||
"hidden": "Skrýt v kalendáři",
|
||||
"frequency": "Frekvence",
|
||||
"manual_update": "Manual update - state je aktualizovaný manuálně voláním služby",
|
||||
"icon_normal": "Ikona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Ikona svoz zítra (mdi:delete-restore)",
|
||||
"icon_today": "Ikona svoz dnes (mdi:delete-circle)",
|
||||
"expire_after": "Čas expirace (HH:MM)",
|
||||
"verbose_state": "Verbose state (popis místo čísel)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Další parametry (2/2)",
|
||||
"description": "Více na: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Seznam entit (odděleno čárkou)",
|
||||
"collection_days": "Dny svozu",
|
||||
"first_month": "První měsíc svozu",
|
||||
"last_month": "Poslední měsíc svozu",
|
||||
"period": "Perioda (svoz každých n týdnů/dnů): (1-1000)",
|
||||
"first_week": "První týden svozu (1-52)",
|
||||
"first_date": "První datum",
|
||||
"weekday_order_number": "Pořadí dne v měsící (např. první středa v měsíci)",
|
||||
"force_week_order_numbers": "Číslo týdne v měsící místo čísla dne",
|
||||
"verbose_format": "Verbose format (Použij `date` a `days` proměnné (ve složených závorkách))",
|
||||
"date_format": "Formát data(see http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Chybná hodnota. Zkontroluj zadané hodnoty!",
|
||||
"icon": "Ikony musí být zadány ve formátu 'prefix:jmnéno'.",
|
||||
"days": "Vyber jeden nebo více dní!",
|
||||
"entities": "Entita neexistuje!",
|
||||
"month_day": "Špatný formát data!",
|
||||
"time": "Špatný formát času!",
|
||||
"weekday_order_number": "Vyber jeden nebo více dní!",
|
||||
"week_order_number": "Vyber jeden nebo více týdnů!",
|
||||
"period": "Perioda musí být číslo mezi 1 a 1000",
|
||||
"first_week": "První týden musí být číslo mezi 1 a 52",
|
||||
"date": "Špatný formát data!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Only a single configuration of Garbage Collection is allowed."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Garbage Collection - Konfigurace (1/2)",
|
||||
"description": "Zadej jméno sensoru a nastav parametry. Více na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Skrýt v kalendáři",
|
||||
"frequency": "Frekvence",
|
||||
"manual_update": "State je aktualizovaný manuálně voláním služby",
|
||||
"icon_normal": "Ikona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Ikona svoz zítra (mdi:delete-restore)",
|
||||
"icon_today": "Ikona svoz dnes (mdi:delete-circle)",
|
||||
"expire_after": "Čas expirace (HH:MM)",
|
||||
"verbose_state": "Verbose state (popis místo čísel)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Další parametry (2/2)",
|
||||
"description": "",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Seznam entit (odděleno čárkou)",
|
||||
"collection_days": "Dny svozu",
|
||||
"first_month": "První měsíc svozu",
|
||||
"last_month": "Poslední měsíc scozu",
|
||||
"period": "Perioda (svoz každých n týdnů-dnů): (1-1000)",
|
||||
"first_week": "První týden svozu (1-52)",
|
||||
"first_date": "První datum",
|
||||
"weekday_order_number": "Pořadí dne v měsící (např. první středa v měsíci)",
|
||||
"force_week_order_numbers": "Číslo týdne v měsící místo čísla dne",
|
||||
"verbose_format": "Verbose format (Použij `date` a `days` proměnné (ve složených závorkách))",
|
||||
"date_format": "Formát data(see http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Chybná hodnota. Zkontroluj zadané hodnoty!",
|
||||
"icon": "Ikony musí být zadány ve formátu 'prefix:jmnéno'.",
|
||||
"days": "Vyber jeden nebo více dní!",
|
||||
"entities": "Entita neexistuje!",
|
||||
"month_day": "Špatný formát data!",
|
||||
"time": "Špatný formát času!",
|
||||
"weekday_order_number": "Vyber jeden nebo více dní!",
|
||||
"week_order_number": "Vyber jeden nebo více týdnů!",
|
||||
"period": "Perioda musí být číslo mezi 1 a 1000",
|
||||
"first_week": "První týden musí být číslo mezi 1 a 52",
|
||||
"date": "Špatný formát data!"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Garbage Collection - Afhentningsfrekvens (1/2)",
|
||||
"description": "Angiv navnet på sensoren og konfigurer sensorparametre. For mere info se: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Visningsnavn",
|
||||
"hidden": "Skjul i kalender",
|
||||
"frequency": "Frekvens",
|
||||
"manual_update": "Manuel opdatering - sensortilstand opdateres manuelt af en service (blueprint)",
|
||||
"icon_normal": "Ikon (mdi:trash-can) - ikke påkrævet",
|
||||
"icon_tomorrow": "Ikon ved afhentning i morgen (mdi:delete-restore) - ikke påkrævet",
|
||||
"icon_today": "Ikon ved afhentning i dag (mdi:delete-circle) - ikke påkrævet",
|
||||
"expire_after": "Forældes efter (HH:MM) - ikke påkrævet",
|
||||
"verbose_state": "Verbos tilstand (tekst i stedet for tal)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Yderligere parametre (2/2)",
|
||||
"description": "For mere info se: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Dato (mm/dd)",
|
||||
"entities": "Liste af enheder (kommasepareret)",
|
||||
"collection_days": "Afhentningsdage",
|
||||
"first_month": "Første afhentningsmåned",
|
||||
"last_month": "Sidste afhentningsmåned",
|
||||
"period": "Afhentning sker hver n uger/dage: (1-1000)",
|
||||
"first_week": "Første afhentningsuge (1-52)",
|
||||
"first_date": "Første dato",
|
||||
"weekday_order_number": "Specifikke ugedage i måneden (fx første onsdag i måneden)",
|
||||
"force_week_order_numbers": "Brug specifik uge i måneden i stedet for specifik ugedag (fx onsdag i første uge i måneden)",
|
||||
"verbose_format": "Verbost format (anvend `date` og `days` variablerne (i tuborgklammer))",
|
||||
"date_format": "Datoformat (se http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Ugyldig værdi. Check dit input!",
|
||||
"icon": "Ikoner skal angives i formen 'præfiks:navn'.",
|
||||
"days": "Vælg en eller flere dage!",
|
||||
"entities": "Enheden findes ikke!",
|
||||
"month_day": "Ugyldigt dato format!",
|
||||
"time": "Ugyldigt tids format!",
|
||||
"weekday_order_number": "Vælg en eller flere dage",
|
||||
"week_order_number": "Vælg en eller flere uger",
|
||||
"period": "Afhentningsperioden skal være et tal mellem 1 og 1000",
|
||||
"first_week": "Første afhentningsuge skal være et tal mellem 1 and 52",
|
||||
"date": "Ugyldigt dato format!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Det er kun tilladt at have én konfiguration af Garbage Collection."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Garbage Collection - Afhentningsfrekvens (1/2)",
|
||||
"description": "Ændr sensorparametre. More info on https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Skjul i kalender",
|
||||
"frequency": "Frekvens",
|
||||
"manual_update": "Manuel opdatering - sensortilstand opdateres manuelt af en service (blueprint)",
|
||||
"icon_normal": "Ikon (mdi:trash-can) - ikke påkrævet",
|
||||
"icon_tomorrow": "Ikon ved afhentning i morgen (mdi:delete-restore) - ikke påkrævet",
|
||||
"icon_today": "Ikon ved afhentning i dag (mdi:delete-circle) - ikke påkrævet",
|
||||
"expire_after": "Forældes efter (HH:MM) - ikke påkrævet",
|
||||
"verbose_state": "Verbos tilstand (tekst i stedet for tal)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Yderligere parametre (2/2)",
|
||||
"description": "For mere info se: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Dato (mm/dd)",
|
||||
"entities": "Liste af enheder (kommasepareret)",
|
||||
"collection_days": "Afhentningsdage",
|
||||
"first_month": "Første afhentningsmåned",
|
||||
"last_month": "Sidste afhentningsmåned",
|
||||
"period": "Afhentning sker hver n uger/dage: (1-1000)",
|
||||
"first_week": "Første afhentningsuge (1-52)",
|
||||
"first_date": "Første dato",
|
||||
"weekday_order_number": "Specifikke ugedage i måneden (fx første onsdag i måneden)",
|
||||
"force_week_order_numbers": "Brug specifik uge i måneden i stedet for specifik ugedag (fx onsdag i første uge i måneden)",
|
||||
"verbose_format": "Verbost format (anvend `date` og `days` variablerne (i tuborgklammer))",
|
||||
"date_format": "Datoformat (se http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Ugyldig værdi. Check dit input!",
|
||||
"icon": "Ikoner skal angives i formen 'præfiks:navn'.",
|
||||
"days": "Vælg en eller flere dage!",
|
||||
"entities": "Enheden findes ikke!",
|
||||
"month_day": "Ugyldigt dato format!",
|
||||
"time": "Ugyldigt tids format!",
|
||||
"weekday_order_number": "Vælg en eller flere dage",
|
||||
"week_order_number": "Vælg en eller flere uger",
|
||||
"period": "Afhentningsperioden skal være et tal mellem 1 og 1000",
|
||||
"first_week": "Første afhentningsuge skal være et tal mellem 1 and 52",
|
||||
"date": "Ugyldigt dato format!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Müllabfuhr - Häufigkeit der Abholung (1/2)",
|
||||
"description": "Geben Sie den Sensornamen ein und konfigurieren Sie die Sensorparameter. Mehr Informationen unter https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Friendly Name",
|
||||
"hidden": "Im Kalender ausblenden",
|
||||
"frequency": "Häufigkeit",
|
||||
"manual_update": "Manuelle Aktualisierung - Sensorstatus wird manuell durch einen Dienst aktualisiert (Vorlage)",
|
||||
"icon_normal": "Icon (mdi:trash-can) - optional",
|
||||
"icon_tomorrow": "Icon Abfuhr morgen (mdi:delete-restore) - optional",
|
||||
"icon_today": "Icon Abfuhr heute (mdi:delete-circle) - optional",
|
||||
"expire_after": "Ablauf nach (HH:MM) - optional",
|
||||
"verbose_state": "Ausführlicher Status (Text, statt Zahl)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Müllabfuhr - Zusätzliche Parameter (2/2)",
|
||||
"description": "Mehr Details hier: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Liste der Entitäten (durch Komma getrennt)",
|
||||
"collection_days": "Tage der Abholung",
|
||||
"first_month": "Erster Abholungsmonat",
|
||||
"last_month": "Letzter Abholungsmonat",
|
||||
"period": "Abholung alle n Wochen/Tage: (1-1000)",
|
||||
"first_week": "Erste Abholungswoche (1-52)",
|
||||
"first_date": "Erstes Datum",
|
||||
"weekday_order_number": "Reihenfolge der Wochentage im Monat (z. B. erster Mittwoch im Monat)",
|
||||
"force_week_order_numbers": "Reihenfolge der Woche im Monat statt Wochentagsreihenfolge (z. B. am Mittwoch der ersten Woche)",
|
||||
"verbose_format": "Ausführliches Format (unter Verwendung der Variablen 'Datum' und 'Tage' (in eckigen Klammern))",
|
||||
"date_format": "Datumsformat (siehe http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Ungültiger Wert. Bitte überprüfen Sie Ihre Eingabe!",
|
||||
"icon": "Icons sollten in der Form 'Präfix:Name' angegeben werden.",
|
||||
"days": "Wählen Sie 1 oder mehrere Tage aus!",
|
||||
"entities": "Entität existiert nicht!",
|
||||
"month_day": "Ungültiges Datumsformat!",
|
||||
"time": "Ungültiges Zeitformat!",
|
||||
"weekday_order_number": "Wählen Sie 1 oder mehrere Tage aus",
|
||||
"week_order_number": "Wählen Sie 1 oder mehrere Wochen aus",
|
||||
"period": "Zeitraum muss eine Zahl zwischen 1 und 1000 sein",
|
||||
"first_week": "Erste Woche muss eine Zahl zwischen 1 und 52 sein",
|
||||
"date": "Ungültiges Datumsformat!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Es ist nur eine einzige Konfiguration von Garbage Collection erlaubt."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Müllabfuhr - Häufigkeit der Abholung (1/2)",
|
||||
"description": "Sensorparameter ändern. Mehr Informationen unter https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Im Kalender ausblenden",
|
||||
"frequency": "Häufigkeit",
|
||||
"manual_update": "Manuelle Aktualisierung - Sensorstatus wird manuell durch einen Dienst aktualisiert (Vorlage)",
|
||||
"icon_normal": "Icon (mdi:trash-can) - optional",
|
||||
"icon_tomorrow": "Icon Abfuhr morgen (mdi:delete-restore) - optional",
|
||||
"icon_today": "Icon Abfuhr heute (mdi:delete-circle) - optional",
|
||||
"expire_after": "Ablauf nach (HH:MM) - optional",
|
||||
"verbose_state": "Ausführlicher Status (Text, statt Zahl)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Müllabfuhr - Zusätzliche Parameter (2/2)",
|
||||
"description": "Mehr Details hier: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Liste der Entitäten (durch Komma getrennt)",
|
||||
"collection_days": "Tage der Abholung",
|
||||
"first_month": "Erster Abholungsmonat",
|
||||
"last_month": "Letzter Abholungsmonat",
|
||||
"period": "Abholung alle n Wochen/Tage: (1-1000)",
|
||||
"first_week": "Erste Abholungswoche (1-52)",
|
||||
"first_date": "Erstes Datum",
|
||||
"weekday_order_number": "Reihenfolge der Wochentage im Monat (z. B. erster Mittwoch im Monat)",
|
||||
"force_week_order_numbers": "Reihenfolge der Woche im Monat statt Wochentagsreihenfolge (z. B. am Mittwoch der ersten Woche)",
|
||||
"verbose_format": "Ausführliches Format (unter Verwendung der Variablen 'Datum' und 'Tage' (in eckigen Klammern))",
|
||||
"date_format": "Datumsformat (siehe http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Ungültiger Wert. Bitte überprüfen Sie Ihre Eingabe!",
|
||||
"icon": "Icons sollten in der Form 'Präfix:Name' angegeben werden.",
|
||||
"days": "Wählen Sie 1 oder mehrere Tage aus!",
|
||||
"entities": "Entität existiert nicht!",
|
||||
"month_day": "Ungültiges Datumsformat!",
|
||||
"time": "Ungültiges Zeitformat!",
|
||||
"weekday_order_number": "Wählen Sie 1 oder mehrere Tage aus",
|
||||
"week_order_number": "Wählen Sie 1 oder mehrere Wochen aus",
|
||||
"period": "Zeitraum muss eine Zahl zwischen 1 und 1000 sein",
|
||||
"first_week": "Erste Woche muss eine Zahl zwischen 1 und 52 sein",
|
||||
"date": "Ungültiges Datumsformat!"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Garbage Collection - Collection frequency (1/2)",
|
||||
"description": "Enter the sensor name and configure sensor parameters. More info on https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Friendly name",
|
||||
"hidden": "Hide in calendar",
|
||||
"frequency": "Frequency",
|
||||
"manual_update": "Manual update - sensor state updated manually by a service (Blueprint)",
|
||||
"icon_normal": "Icon (mdi:trash-can) - optional",
|
||||
"icon_tomorrow": "Icon collection tomorrow (mdi:delete-restore) - optional",
|
||||
"icon_today": "Icon collection today (mdi:delete-circle) - optional",
|
||||
"expire_after": "Expire after (HH:MM) - optional",
|
||||
"verbose_state": "Verbose state (text, instead of number)",
|
||||
"move_country_holidays": "Shift collection if a public holiday falls in the week",
|
||||
"holiday_country": "Country code for public holidays (e.g. FR)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Additional parameters (2/2)",
|
||||
"description": "More details here: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Date (mm/dd)",
|
||||
"entities": "List of entities (comma separated)",
|
||||
"collection_days": "Collection days",
|
||||
"first_month": "First collection month",
|
||||
"last_month": "Last collection month",
|
||||
"period": "Collection every n weeks/days: (1-1000)",
|
||||
"first_week": "First collection week (1-52)",
|
||||
"first_date": "First date",
|
||||
"weekday_order_number": "Order of the weekday in the month (e.g. first Wednesday of the month)",
|
||||
"force_week_order_numbers": "Order of week in a month instead of order of weekday (e.g. on Wednesday of the first week)",
|
||||
"verbose_format": "Verbose format (using `date` and `days` variables (in squary brackets))",
|
||||
"date_format": "Date format (see http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Invalid value. Please check your input!",
|
||||
"icon": "Icons should be specified in the form 'prefix:name'.",
|
||||
"days": "Select 1 or more days!",
|
||||
"entities": "Entity does not exist!",
|
||||
"month_day": "Invalid date format!",
|
||||
"time": "Invalid time format!",
|
||||
"weekday_order_number": "Select 1 or more days",
|
||||
"week_order_number": "Select 1 or more weeks",
|
||||
"period": "Period must be a number between 1 and 1000",
|
||||
"first_week": "First week must be a number between 1 and 52",
|
||||
"date": "Invalid date format!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Only a single configuration of Garbage Collection is allowed."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Garbage Collection - Collection frequency (1/2)",
|
||||
"description": "Change sensor parameters. More info on https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Hide in calendar",
|
||||
"frequency": "Frequency",
|
||||
"manual_update": "Manual update - sensor state updated manually by a service (Blueprint)",
|
||||
"icon_normal": "Icon (mdi:trash-can) - optional",
|
||||
"icon_tomorrow": "Icon collection tomorrow (mdi:delete-restore) - optional",
|
||||
"icon_today": "Icon collection today (mdi:delete-circle) - optional",
|
||||
"expire_after": "Expire after (HH:MM) - optional",
|
||||
"verbose_state": "Verbose state (text, instead of number)",
|
||||
"move_country_holidays": "Shift collection if a public holiday falls in the week",
|
||||
"holiday_country": "Country code for public holidays (e.g. FR)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Additional parameters (2/2)",
|
||||
"description": "More details here: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Date (mm/dd)",
|
||||
"entities": "List of entities (comma separated)",
|
||||
"collection_days": "Collection days",
|
||||
"first_month": "First collection month",
|
||||
"last_month": "Last collection month",
|
||||
"period": "Collection every n weeks/days: (1-1000)",
|
||||
"first_week": "First collection week (1-52)",
|
||||
"first_date": "First date",
|
||||
"weekday_order_number": "Order of the weekday in the month (e.g. first Wednesday of the month)",
|
||||
"force_week_order_numbers": "Order of week in a month instead of order of weekday (e.g. on Wednesday of the first week)",
|
||||
"verbose_format": "Verbose format (using `date` and `days` variables (in squary brackets))",
|
||||
"date_format": "Date format (see http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Invalid value. Please check your input!",
|
||||
"icon": "Icons should be specified in the form 'prefix:name'.",
|
||||
"days": "Select 1 or more days!",
|
||||
"entities": "Entity does not exist!",
|
||||
"month_day": "Invalid date format!",
|
||||
"time": "Invalid time format!",
|
||||
"weekday_order_number": "Select 1 or more days",
|
||||
"week_order_number": "Select 1 or more weeks",
|
||||
"period": "Period must be a number between 1 and 1000",
|
||||
"first_week": "First week must be a number between 1 and 52",
|
||||
"date": "Invalid date format!"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Recolección de basura - Frecuencia de recogida (1/2)",
|
||||
"description": "Ingrese el nombre del sensor y configure los parámetros del sensor. Más información en https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Nombre amigable",
|
||||
"hidden": "Esconderse en el calendario",
|
||||
"frequency": "Frequencia",
|
||||
"manual_update": "El estado del sensor se actualiza manualmente llamando a un servicio",
|
||||
"icon_normal": "Icono (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icono de recoleccion para mañana (mdi:delete-restore)",
|
||||
"icon_today": "Icono de recoleccion para hoy (mdi:delete-circle)",
|
||||
"expire_after": "Caduca después (HH:MM)",
|
||||
"verbose_state": "Estado detallado (texto, en lugar de número)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Recolección de basura - Parámetros adicionales (2/2)",
|
||||
"description": "Más detalles aquí: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Fecha (mm/dd)",
|
||||
"entities": "Lista de entidades (separadas por comas)",
|
||||
"collection_days": "Días de recogida",
|
||||
"first_month": "Primer mes de recogida",
|
||||
"last_month": "Último mes de recogida",
|
||||
"period": "Recolección cada n semanas / días: (1-1000)",
|
||||
"first_week": "Primera semana de recolección (1-52)",
|
||||
"first_date": "Primera fecha",
|
||||
"weekday_order_number": "Orden del día de la semana en el mes (por ejemplo, primer miércoles del mes)",
|
||||
"force_week_order_numbers": "Orden de la semana en un mes en lugar de orden del día de la semana (por ejemplo, el miércoles de la primera semana)",
|
||||
"verbose_format": "Formato detallado (usando las variables `fecha` y` dias` (entre corchetes))",
|
||||
"date_format": "Formato de fecha(ver en http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valor no válido. Por favor revise su entrada!",
|
||||
"icon": "Los iconos deben especificarse en el formato 'prefix:name'.",
|
||||
"days": "Seleccione 1 o más días!",
|
||||
"entities": "La entidad no existe!",
|
||||
"month_day": "Formato de fecha inválido!",
|
||||
"time": "Formato de hora inválido!",
|
||||
"weekday_order_number": "Seleccione 1 o más días",
|
||||
"week_order_number": "Seleccione 1 o más semanas",
|
||||
"period": "El período debe ser un número entre 1 y 1000",
|
||||
"first_week": "La primera semana debe ser un número entre 1 y 52",
|
||||
"date": "Formato de fecha inválido!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Solo se permite una única configuración de Recolección de basura."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Recolección de basura - Frecuencia de recogida (1/2)",
|
||||
"description": "Cambiar los parámetros del sensor. Más información en https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Esconderse en el calendario",
|
||||
"frequency": "Frequencia",
|
||||
"manual_update": "El estado del sensor se actualiza manualmente llamando a un servicio",
|
||||
"icon_normal": "Icono (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icono de recoleccion para mañana (mdi:delete-restore)",
|
||||
"icon_today": "Icono de recoleccion para hoy (mdi:delete-circle)",
|
||||
"expire_after": "Caduca después (HH:MM)",
|
||||
"verbose_state": "Estado detallado (texto, en lugar de número)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Recolección de basura - Parámetros adicionales (2/2)",
|
||||
"description": "Más detalles aquí: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Fecha (mm/dd)",
|
||||
"entities": "Lista de entidades (separadas por comas)",
|
||||
"collection_days": "Días de recogida",
|
||||
"first_month": "Primer mes de recogida",
|
||||
"last_month": "Último mes de recogida",
|
||||
"period": "Recolección cada n semanas / días: (1-1000)",
|
||||
"first_week": "Primera semana de recolección (1-52)",
|
||||
"first_date": "Primera fecha",
|
||||
"weekday_order_number": "Orden del día de la semana en el mes (por ejemplo, primer miércoles del mes)",
|
||||
"force_week_order_numbers": "Orden de la semana en un mes en lugar de orden del día de la semana (por ejemplo, el miércoles de la primera semana)",
|
||||
"verbose_format": "Formato detallado (usando las variables `fecha` y` dias` (entre corchetes))",
|
||||
"date_format": "Formato de fecha(ver en http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valor no válido. Por favor revise su entrada!",
|
||||
"icon": "Los iconos deben especificarse en el formato 'prefix:name'.",
|
||||
"days": "Seleccione 1 o más días!",
|
||||
"entities": "La entidad no existe!",
|
||||
"month_day": "Formato de fecha inválido!",
|
||||
"time": "Formato de hora inválido!",
|
||||
"weekday_order_number": "Seleccione 1 o más días",
|
||||
"week_order_number": "Seleccione 1 o más semanas",
|
||||
"period": "El período debe ser un número entre 1 y 1000",
|
||||
"first_week": "La primera semana debe ser un número entre 1 y 52",
|
||||
"date": "Formato de fecha inválido!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Prügivedu - tühjendamiste ajad (1/2)",
|
||||
"description": "Sisesta nduri andmed. Rohkem infot leiab https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Kuvatav nimi",
|
||||
"hidden": "Ära näita kalendris",
|
||||
"frequency": "Sagedus",
|
||||
"manual_update": "Sensor state updated manually by calling a service",
|
||||
"icon_normal": "Ikoon (mdi:trash-can) - valikuline",
|
||||
"icon_tomorrow": "Homme on prügivedu ikoon (mdi:delete-restore) - valikuline",
|
||||
"icon_today": "Täna on prügivedu ikoon (mdi:delete-circle) - valikuline",
|
||||
"expire_after": "Ajalõpp (HH:MM) - valikuline",
|
||||
"verbose_state": "Teavitus tekstina (aeg tekstina numbrite asemel)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Prügivedu - täiendavad sätted (2/2)",
|
||||
"description": "Vali üks või mitu tühjendamise nädalapäeva. Rohkem teavet: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Kuupäev (mm/dd)",
|
||||
"entities": "Olemite nimekiri (komadega eraldatud)",
|
||||
"collection_days": "Tühjendamise nädalapäevad",
|
||||
"first_month": "Esimene prügiveo kuu",
|
||||
"last_month": "Viimane prügiveo kuu",
|
||||
"period": "Prügivedu iga n päeva/nädala tagant: (1-1000)",
|
||||
"first_week": "Esimese prügiveo nädal (1-52)",
|
||||
"first_date": "Esimese prügiveo kuupäev",
|
||||
"weekday_order_number": "Kuu nädalapäevade järjekord (nt kuu esimene kolmapäev)",
|
||||
"force_week_order_numbers": "nädala järjekord kuus, mitte nädalapäevade järjekord (nt esimese nädala kolmapäeval).",
|
||||
"verbose_format": "Teavituse formaat (kasutades `date` and `days` muutujaid (kantsulgudes))",
|
||||
"date_format": "Kuupäeva formaat (vaata http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Vigane sisestus, palun kontrolli!",
|
||||
"icon": "Ikoonid tuleb esitada kujul 'prefix:name'.",
|
||||
"days": "Valige üks või rohkem päevi!",
|
||||
"entities": "Olem puudub!",
|
||||
"month_day": "Vigane kuupäeva formaat!",
|
||||
"time": "Vigane kellaaja formaat!",
|
||||
"weekday_order_number": "Valige üks või rohkem päevi",
|
||||
"week_order_number": "Valige üks või rohkem nädalat",
|
||||
"period": "Välp peab olema number 1 ja 1000 vahel",
|
||||
"first_week": "Esimene nädal peab olema number 1 ja 52 vahel",
|
||||
"date": "Vigane kuupäeva formaat!!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Lubatud on ainult üks prügiveo olemi sidumine."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Prügivedu - tühjendamiste ajad (1/2)",
|
||||
"description": "Sisesta nduri andmed. Rohkem infot leiab https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Ära näita kalendris",
|
||||
"frequency": "Sagedus",
|
||||
"manual_update": "Sensor state updated manually by calling a service",
|
||||
"icon_normal": "Ikoon (mdi:trash-can) - valikuline",
|
||||
"icon_tomorrow": "Homme on prügivedu ikoon (mdi:delete-restore) - valikuline",
|
||||
"icon_today": "Täna on prügivedu ikoon (mdi:delete-circle) - valikuline",
|
||||
"expire_after": "Ajalõpp (HH:MM) - valikuline",
|
||||
"verbose_state": "Teavitus tekstina (aeg tekstina numbrite asemel)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Prügivedu - täiendavad sätted (2/2)",
|
||||
"description": "Vali üks või mitu tühjendamise nädalapäeva. Rohkem teavet: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Kuupäev (mm/dd)",
|
||||
"entities": "Olemite nimekiri (komadega eraldatud)",
|
||||
"collection_days": "Tühjendamise nädalapäevad",
|
||||
"first_month": "Esimene prügiveo kuu",
|
||||
"last_month": "Viimane prügiveo kuu",
|
||||
"period": "Prügivedu iga n päeva/nädala tagant: (1-1000)",
|
||||
"first_week": "Esimese prügiveo nädal (1-52)",
|
||||
"first_date": "Esimese prügiveo kuupäev",
|
||||
"weekday_order_number": "Kuu nädalapäevade järjekord (nt kuu esimene kolmapäev)",
|
||||
"force_week_order_numbers": "nädala järjekord kuus, mitte nädalapäevade järjekord (nt esimese nädala kolmapäeval).",
|
||||
"verbose_format": "Teavituse formaat (kasutades `date` and `days` muutujaid (kantsulgudes))",
|
||||
"date_format": "Kuupäeva formaat (vaata http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Vigane sisestus, palun kontrolli!",
|
||||
"icon": "Ikoonid tuleb esitada kujul 'prefix:name'.",
|
||||
"days": "Valige üks või rohkem päevi!",
|
||||
"entities": "Olem puudub!",
|
||||
"month_day": "Vigane kuupäeva formaat!",
|
||||
"time": "Vigane kellaaja formaat!",
|
||||
"weekday_order_number": "Valige üks või rohkem päevi",
|
||||
"week_order_number": "Valige üks või rohkem nädalat",
|
||||
"period": "Välp peab olema number 1 ja 1000 vahel",
|
||||
"first_week": "Esimene nädal peab olema number 1 ja 52 vahel",
|
||||
"date": "Vigane kuupäeva formaat!!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Garbage Collection - Fréquence de la collecte (1/2)",
|
||||
"description": "Définir le nom du capteur et configurer les paramètres du capteur. Plus d'info sur https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Friendly name",
|
||||
"hidden": "Masquer dans le calendrier",
|
||||
"frequency": "Fréquence",
|
||||
"manual_update": "État du capteur mis à jour manuellement en appelant un service",
|
||||
"icon_normal": "Icône (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icône pour collecte à jour J+1 (mdi:delete-restore)",
|
||||
"icon_today": "Icône pour collecte au jour J (mdi:delete-circle)",
|
||||
"offset": "Décalage (entre -31 et 31 jours)",
|
||||
"expire_after": "Expire après (HH:MM)",
|
||||
"verbose_state": "Etat verbeux (texte, au lieu du chiffre)",
|
||||
"move_country_holidays": "Décaler la collecte si jour férié dans la semaine",
|
||||
"holiday_country": "Code pays pour les jours fériés (ex: FR)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Paramètres additionnels (2/2)",
|
||||
"description": "Choisir un ou plusieurs jours de collecte. Plus de détail ici: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Date (mm/dd)",
|
||||
"entities": "Liste des entités (séparées par une virgule)",
|
||||
"collection_days": "Jours de collecte",
|
||||
"first_month": "Premier mois de la collecte",
|
||||
"last_month": "Dernier mois de la collecte",
|
||||
"period": "Collecte toutes les n semaines/jours: (1-1000)",
|
||||
"first_week": "Première semaine de la collecte (1-52)",
|
||||
"first_date": "Première date",
|
||||
"weekday_order_number": "Ordre du jour de la semaine dans le mois (par exemple, premier mercredi du mois)",
|
||||
"force_week_order_numbers": "Nième occurrence du jour de la semaine dans un mois, au lieu du jour de la semaine dans la Nième semaine de chaque mois. Plus d'info sur https://github.com/bruxy70/Garbage-Collection#parameters-for-monthly-collection",
|
||||
"verbose_format": "Format état verbeux (utilisation des variables `date` et `days` (entre caractères accolade ))",
|
||||
"date_format": "Format de date (voir http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valeur invalide. Veuillez vérifier votre saisie !",
|
||||
"icon": "Les icônes doivent être spécifiées dans le format 'prefix:name'.",
|
||||
"days": "Choisir un ou plusieurs jours !",
|
||||
"entities": "L'entité n'existe pas !",
|
||||
"month_day": "Format de date invalide !",
|
||||
"time": "Format d'heure invalide !",
|
||||
"weekday_order_number": "Choisir un ou plusieurs jours",
|
||||
"week_order_number": "Choisir une ou plusieurs semaines",
|
||||
"period": "La semaine doit être un nombre entre 1 et 1000",
|
||||
"first_week": "La première semaine doit être un nombre entre 1 et 52",
|
||||
"date": "Format de date invalide !"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Une seule configuration de Garbage Collection est autorisée"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Garbage Collection - Fréquence de la collecte (1/2)",
|
||||
"description": "Modifier les paramètres des capteurs. Plus d'infos sur https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Masquer dans le calendrier",
|
||||
"frequency": "Fréquence",
|
||||
"manual_update": "État du capteur mis à jour manuellement en appelant un service",
|
||||
"icon_normal": "Icône (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icône pour collecte à jour J+1 (mdi:delete-restore)",
|
||||
"icon_today": "Icône pour collecte au jour J (mdi:delete-circle)",
|
||||
"offset": "Décalage (entre -31 et 31 jours)",
|
||||
"expire_after": "Expire après (HH:MM)",
|
||||
"verbose_state": "Etat verbeux (texte, au lieu du chiffre)",
|
||||
"move_country_holidays": "Décaler la collecte si jour férié dans la semaine",
|
||||
"holiday_country": "Code pays pour les jours fériés (ex: FR)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Paramètres additionnels (2/2)",
|
||||
"description": "Choisir un ou plusieurs jours de collecte. Plus de détail ici: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Date (mm/dd)",
|
||||
"entities": "Liste des entités (séparées par une virgule)",
|
||||
"collection_days": "Jours de collecte",
|
||||
"first_month": "Premier mois de la collecte",
|
||||
"last_month": "Dernier mois de la collecte",
|
||||
"period": "Collecte toutes les n semaines/jours: (1-1000)",
|
||||
"first_week": "Première semaine de la collecte (1-52)",
|
||||
"first_date": "Première date",
|
||||
"weekday_order_number": "Ordre du jour de la semaine dans le mois (par exemple, premier mercredi du mois)",
|
||||
"force_week_order_numbers": "Nième occurrence du jour de la semaine dans un mois, au lieu du jour de la semaine dans la Nième semaine de chaque mois. Plus d'info sur https://github.com/bruxy70/Garbage-Collection#parameters-for-monthly-collection",
|
||||
"verbose_format": "Format état verbeux (utilisation des variables `date` et `days` (entre caractères accolade ))",
|
||||
"date_format": "Format de date (voir http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valeur invalide. Veuillez vérifier votre saisie !",
|
||||
"icon": "Les icônes doivent être spécifiées dans le format 'prefix:name'.",
|
||||
"days": "Choisir un ou plusieurs jours !",
|
||||
"entities": "L'entité n'existe pas !",
|
||||
"month_day": "Format de date invalide !",
|
||||
"time": "Format d'heure invalide !",
|
||||
"weekday_order_number": "Choisir un ou plusieurs jours",
|
||||
"week_order_number": "Choisir une ou plusieurs semaines",
|
||||
"period": "La semaine doit être un nombre entre 1 et 1000",
|
||||
"first_week": "La première semaine doit être un nombre entre 1 et 52",
|
||||
"date": "Format de date invalide !"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Raccolta Differenziata - Frequenza di raccolta (1/2)",
|
||||
"description": "Immetti il nome del sensore e configura i suoi parametri. Maggiori informazioni su https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Nome personalizzato",
|
||||
"hidden": "Nascondi nel calendario",
|
||||
"frequency": "Frequenza",
|
||||
"manual_update": "Stato del sensore aggiornato manualmente chiamando un servizio",
|
||||
"icon_normal": "Icona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icona raccolta domani (mdi:delete-restore)",
|
||||
"icon_today": "Icona raccolta oggi (mdi:delete-circle)",
|
||||
"expire_after": "Scade dopo (HH:MM) - opzionale",
|
||||
"verbose_state": "Stato Verbale (testo, al posto di numeri)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Raccolta Differenziata - Parametri aggiuntivi (2/2)",
|
||||
"description": "Seleziona uno o più giorni di raccolta. Maggiori dettagli qui: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista di entità (separate da virgole)",
|
||||
"collection_days": "Giorni di raccolta",
|
||||
"first_month": "Prima raccolta del mese",
|
||||
"last_month": "Ultima raccolta del mese",
|
||||
"period": "Raccolta ogni n settimane/giorno: (1-1000)",
|
||||
"first_week": "Prima raccolta della settimana (1-52)",
|
||||
"first_date": "Prima date",
|
||||
"weekday_order_number": "Ordine del giorno della settimana nel mese (ad esempio il primo mercoledì del mese)",
|
||||
"force_week_order_numbers": "Ordine della settimana in un mese invece dell'ordine del giorno della settimana (per esempio il mercoledì della prima settimana)",
|
||||
"verbose_format": "Formato Verbale (usare le variabili `date` e `days` (in parentesi graffe))",
|
||||
"date_format": "Formato Data (vedere http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valore non valido. Per favore controlla i tuoi input!",
|
||||
"icon": "Le icone devono essere specificate nel formato 'prefix:name'.",
|
||||
"days": "Seleziona uno o più giorni!",
|
||||
"entities": "L'entità non esiste!",
|
||||
"month_day": "Formato data non valido!",
|
||||
"time": "Formato ora non valido!",
|
||||
"weekday_order_number": "Seleziona uno o più giorni",
|
||||
"week_order_number": "Seleziona uno o più settimani",
|
||||
"period": "Il periodo deve essere un numero compreso tra 1 e 1000",
|
||||
"first_week": "La prima settimana deve essere un numero tra 1 e 52",
|
||||
"date": "Formato data non valido!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "E' consentita solo una singola configurazione di Raccolta Differenziata."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Raccolta Differenziata - Frequenza di raccolta (1/2)",
|
||||
"description": "Cambia i parametri del sensore. Maggiori informazioni su https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Nascondi nel calendario",
|
||||
"frequency": "Frequenza",
|
||||
"manual_update": "Stato del sensore aggiornato manualmente chiamando un servizio",
|
||||
"icon_normal": "Icona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Icona raccolta domani (mdi:delete-restore)",
|
||||
"icon_today": "Icona raccolta oggi (mdi:delete-circle)",
|
||||
"expire_after": "Scade dopo (HH:MM) - opzionale",
|
||||
"verbose_state": "Stato Verbale (testo, al posto di numeri)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Raccolta Differenziata - Parametri aggiuntivi (2/2)",
|
||||
"description": "Seleziona uno o più giorni di raccolta. Maggiori dettagli qui: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista di entità (separate da virgole)",
|
||||
"collection_days": "Giorni di raccolta",
|
||||
"first_month": "Prima raccolta del mese",
|
||||
"last_month": "Ultima raccolta del mese",
|
||||
"period": "Raccolta ogni n settimane/giorno: (1-1000)",
|
||||
"first_week": "Prima raccolta della settimana (1-52)",
|
||||
"first_date": "Prima date",
|
||||
"weekday_order_number": "Ordine del giorno della settimana nel mese (ad esempio il primo mercoledì del mese)",
|
||||
"force_week_order_numbers": "Ordine della settimana in un mese invece dell'ordine del giorno della settimana (per esempio il mercoledì della prima settimana)",
|
||||
"verbose_format": "Formato Verbale (usare le variabili `date` e `days` (in parentesi graffe))",
|
||||
"date_format": "Formato Data (vedere http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valore non valido. Per favore controlla i tuoi input!",
|
||||
"icon": "Le icone devono essere specificate nel formato 'prefix:name'.",
|
||||
"days": "Seleziona uno o più giorni!",
|
||||
"entities": "L'entità non esiste!",
|
||||
"month_day": "Formato data non valido!",
|
||||
"time": "Formato ora non valido!",
|
||||
"weekday_order_number": "Seleziona uno o più giorni",
|
||||
"week_order_number": "Seleziona uno o più settimani",
|
||||
"period": "Il periodo deve essere un numero compreso tra 1 e 1000",
|
||||
"first_week": "La prima settimana deve essere un numero tra 1 e 52",
|
||||
"date": "Formato data non valido!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Wywóz Śmieci - Częstotliwość wywozu (1/2)",
|
||||
"description": "Wprowadź nazwę dla sensora i skonfiguruj jego parametry. Więcej informacji na stronie https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Przyjazna nazwa",
|
||||
"hidden": "Ukryj w kalendarzu",
|
||||
"frequency": "Częstotliwość",
|
||||
"manual_update": "Stan czujnika aktualizowany ręcznie poprzez wywołanie usługi",
|
||||
"icon_normal": "Ikona (mdi:trash-can) - opcjonalnie",
|
||||
"icon_tomorrow": "Ikona wywozu jutro (mdi:delete-restore) - opcjonalnie",
|
||||
"icon_today": "Ikona wywozu dzisiaj (mdi:delete-circle) - opcjonalnie",
|
||||
"expire_after": "Wygasają po (HH:MM) - opcjonalnie",
|
||||
"verbose_state": "Tryb gadatliwy (tekst, zamiast liczb)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Wywóz Śmieci - (2/2)",
|
||||
"description": "Wybierz jeden lub więcej dni wywozu. Więcej szczegółów tutaj: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista encji (rozdzielane przecinkami)",
|
||||
"collection_days": "Dni wywozu",
|
||||
"first_month": "Miesiąc pierwszego wywozu",
|
||||
"last_month": "Miesiąc ostatniego wywozu",
|
||||
"period": "Wywóz co n dni/tygodni: (1-1000)",
|
||||
"first_week": "Tydzień pierwszego wywozu: (1-52)",
|
||||
"first_date": "Pierwsza data",
|
||||
"weekday_order_number": "Kolejność dni tygodnia w miesiącu (np. pierwsza środa miesiąca)",
|
||||
"force_week_order_numbers": "Kolejność tygodni w miesiącu zamiast kolejności dni tygodnia (np. w środę pierwszego tygodnia)",
|
||||
"verbose_format": "Format trybu gadatliwego (używa zmiennych `date` oraz `days` (w nawiasach klamerkowych))",
|
||||
"date_format": "Format daty (patrz http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Niewłaściwa wartość. Sprawdź swoje dane wejściowe!",
|
||||
"icon": "Ikony powinny być określone w formacie 'prefix:name'.",
|
||||
"days": "Wybierz 1 lub więcej dni!",
|
||||
"entities": "Encja nie istnieje!",
|
||||
"month_day": "Nieprawidłowy format daty!",
|
||||
"time": "Nieprawidłowy format czasu!",
|
||||
"weekday_order_number": "Wybierz 1 lub więcej dni!",
|
||||
"week_order_number": "Wybierz 1 lub więcej tygodni!",
|
||||
"period": "Okres musi być liczbą od 1 do 1000.",
|
||||
"first_week": "Pierwszy tydzień musi być liczbą między 1 a 52.",
|
||||
"date": "Nieprawidłowy format daty!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Tylko jedna konfiguracja dla wywozu śmieci jest dozwolona."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Wywóz Śmieci - Częstotliwośc wywozu (1/2)",
|
||||
"description": "Zmień parametry sensora. Więcej informacji tutaj https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Ukryj w kalendarzu",
|
||||
"frequency": "Częstotliwość",
|
||||
"manual_update": "Stan czujnika aktualizowany ręcznie poprzez wywołanie usługi",
|
||||
"icon_normal": "Ikona (mdi:trash-can) - opcjonalnie",
|
||||
"icon_tomorrow": "Ikona wywozu jutro (mdi:delete-restore) - opcjonalnie",
|
||||
"icon_today": "Ikona wywozu dzisiaj (mdi:delete-circle) - opcjonalnie",
|
||||
"expire_after": "Wygasają po (HH:MM) - opcjonalnie",
|
||||
"verbose_state": "Tryb gadatliwy (tekst, zamiast liczb)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Wywóz Śmieci - Dodatkowe parametry (2/2)",
|
||||
"description": "Dołączone i wyłączone daty są listą, rozdzielanych przecinkami, dat w formacie rrrr-mm-dd. Więcej informacji tutaj https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista encji (rozdzielane przecinkami)",
|
||||
"collection_days": "Dni wywozu",
|
||||
"first_month": "Miesiąc pierwszego wywozu",
|
||||
"last_month": "Miesiąc ostatniego wywozu",
|
||||
"period": "Wywóz co n dni/tygodni: (1-1000)",
|
||||
"first_week": "Tydzień pierwszego wywozu: (1-52)",
|
||||
"first_date": "Pierwsza data",
|
||||
"weekday_order_number": "Kolejność dni tygodnia w miesiącu (np. pierwsza środa miesiąca)",
|
||||
"force_week_order_numbers": "Kolejność tygodni w miesiącu zamiast kolejności dni tygodnia (np. w środę pierwszego tygodnia)",
|
||||
"verbose_format": "Format trybu gadatliwego (używa zmiennych `date` oraz `days` (w nawiasach klamrowych))",
|
||||
"date_format": "Format daty (patrz http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Niewłaściwa wartość. Sprawdź swoje dane wejściowe!",
|
||||
"icon": "Ikony powinny być określone w formacie 'prefix:name'.",
|
||||
"days": "Wybierz 1 lub więcej dni!",
|
||||
"entities": "Encja nie istnieje!",
|
||||
"month_day": "Nieprawidłowy format daty!",
|
||||
"time": "Nieprawidłowy format czasu!",
|
||||
"weekday_order_number": "Wybierz 1 lub więcej dni!",
|
||||
"week_order_number": "Wybierz 1 lub więcej tygodni!",
|
||||
"period": "Okres musi być liczbą od 1 do 1000.",
|
||||
"first_week": "Pierwszy tydzień musi być liczbą między 1 a 52.",
|
||||
"date": "Nieprawidłowy format daty!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Coleta de lixo - Frequência de coleta (1/2)",
|
||||
"description": "Insira o nome do sensor e configure os parâmetros do sensor. Mais informações em https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Nome fantasia",
|
||||
"hidden": "Ocultar no calendário",
|
||||
"frequency": "Frequência",
|
||||
"manual_update": "Atualização manual - estado do sensor atualizado manualmente por um serviço (Blueprint)",
|
||||
"icon_normal": "Ícone (mdi:trash-can) - opcional",
|
||||
"icon_tomorrow": "ícones para coleta de amanhã (mdi:delete-restore) - opcional",
|
||||
"icon_today": "Ícones para coleta de hoje (mdi:delete-circle) - opcional",
|
||||
"expire_after": "Expirar depois (HH:MM) - opcional",
|
||||
"verbose_state": "Estado detalhado (texto, em vez de número)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Coleta de lixo - Parâmetros adicionais (2/2)",
|
||||
"description": "Mais detalhes aqui: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista de entidades (separadas por vírgulas)",
|
||||
"collection_days": "Dias de coleta",
|
||||
"first_month": "Primeiro mês de coletah",
|
||||
"last_month": "Último mês de coleta",
|
||||
"period": "Coleta a cada n semanas/dias: (1-1000)",
|
||||
"first_week": "Primeira semana de coleta (1-52)",
|
||||
"first_date": "Primeira data",
|
||||
"weekday_order_number": "Ordem do dia da semana no mês (por exemplo, primeira quarta-feira do mês)",
|
||||
"force_week_order_numbers": "Ordem da semana em um mês em vez da ordem do dia da semana (por exemplo, na quarta-feira da primeira semana)",
|
||||
"verbose_format": "Formato detalhado (usando variáveis `date` e `days` (entre colchetes))",
|
||||
"date_format": "Formato de data (consulte http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valor inválido. Por favor, verifique sua entrada!",
|
||||
"icon": "Os ícones devem ser especificados no formato 'prefix:name'.",
|
||||
"days": "Selecione 1 ou mais dias!",
|
||||
"entities": "A entidade não existe!",
|
||||
"month_day": "Formato de data inválido!",
|
||||
"time": "Formato de hora inválido!",
|
||||
"weekday_order_number": "Selecione 1 ou mais dias",
|
||||
"week_order_number": "Selecione 1 ou mais semanas",
|
||||
"period": "O período deve ser um número entre 1 e 1000",
|
||||
"first_week": "A primeira semana deve ser um número entre 1 e 52",
|
||||
"date": "Formato de data inválido!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Apenas uma única configuração de Coleta de Lixo é permitida."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Coleta de lixo - Frequência de coleta (1/2)",
|
||||
"description": "Altere os parâmetros do sensor. Mais informações em https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Ocultar no calendário",
|
||||
"frequency": "Frequência",
|
||||
"manual_update": "Atualização manual - estado do sensor atualizado manualmente por um serviço (Blueprint)",
|
||||
"icon_normal": "Ícone (mdi:trash-can) - opcional",
|
||||
"icon_tomorrow": "Ícones para coleta de amanhã (mdi:delete-restore) - opcional",
|
||||
"icon_today": "Ícones para coleta de hoje (mdi:delete-circle) - opcional",
|
||||
"expire_after": "Expirar depois (HH:MM) - opcional",
|
||||
"verbose_state": "Estado detalhado (texto, em vez de número)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Coleta de lixo - Parâmetros adicionais (2/2)",
|
||||
"description": "Mais detalhes aqui: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"date": "Data (mm/dd)",
|
||||
"entities": "Lista de entidades (separadas por vírgulas)",
|
||||
"collection_days": "Dias de coleta",
|
||||
"first_month": "Primeiro mês de coleta",
|
||||
"last_month": "Último mês de coleta",
|
||||
"period": "Coleta a cada n semanas/dias: (1-1000)",
|
||||
"first_week": "Primeira semana de coleta (1-52)",
|
||||
"first_date": "Primeira data",
|
||||
"weekday_order_number": "Ordem do dia da semana no mês (por exemplo, primeira quarta-feira do mês)",
|
||||
"force_week_order_numbers": "Ordem da semana em um mês em vez da ordem do dia da semana (por exemplo, na quarta-feira da primeira semana)",
|
||||
"verbose_format": "Formato detalhado (usando variáveis `date` e `days` (entre colchetes))",
|
||||
"date_format": "Formato de data (consulte http://strftime.org/)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Valor inválido. Por favor, verifique sua entrada!",
|
||||
"icon": "Os ícones devem ser especificados no formato 'prefix:name'.",
|
||||
"days": "Selecione 1 ou mais dias!",
|
||||
"entities": "A entidade não existe!",
|
||||
"month_day": "Formato de data inválido!",
|
||||
"time": "Formato de hora inválido!",
|
||||
"weekday_order_number": "Selecione 1 ou mais dias",
|
||||
"week_order_number": "Selecione 1 ou mais semanas",
|
||||
"period": "O período deve ser um número entre 1 e 1000",
|
||||
"first_week": "A primeira semana deve ser um número entre 1 e 52",
|
||||
"date": "Formato de data inválido!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Dnes",
|
||||
"tomorrow": "Zítra"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "I dag",
|
||||
"tomorrow": "I morgen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Heute",
|
||||
"tomorrow": "Morgen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Today",
|
||||
"tomorrow": "Tomorrow"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Hoy",
|
||||
"tomorrow": "Mañana"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Täna",
|
||||
"tomorrow": "Homme"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Aujourd'hui",
|
||||
"tomorrow": "Demain"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Oggi",
|
||||
"tomorrow": "Domani"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Vandaag",
|
||||
"tomorrow": "Morgen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "I morgen",
|
||||
"tomorrow": "I dag"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Dzisiaj",
|
||||
"tomorrow": "Jutro"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Hoje",
|
||||
"tomorrow": "Amanhã"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Idag",
|
||||
"tomorrow": "Imorgon"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Dnes",
|
||||
"tomorrow": "Zajtra"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"state": {
|
||||
"garbage_collection__schedule": {
|
||||
"today": "Danes",
|
||||
"tomorrow": "Jutri"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Garbage Collection - Nastavenia",
|
||||
"description": "Zadej meno senzoru a nastav parametre. Viac na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Friendly name",
|
||||
"hidden": "Skryť v kalendári",
|
||||
"frequency": "Frekvencia",
|
||||
"icon_normal": "Ikona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Ikona zvoz zajtra (mdi:delete-restore)",
|
||||
"icon_today": "Ikona zvoz dnes (mdi:delete-circle)",
|
||||
"offset": "Odsadiť (medzi -31 a 31 dňami)",
|
||||
"expire_after": "Čas expirácie (HH:MM)",
|
||||
"verbose_state": "Verbose state (popis miesto čísiel)",
|
||||
"verbose_format": "Verbose format (Použi `date` a `days` premenné (v zložených zátvorkách))",
|
||||
"include_dates": "Pridané dátumy (yyyy-mm-dd, yyyy-mm-dd, ...) - voliteľné",
|
||||
"exclude_dates": "Zakázané dátumy (yyyy-mm-dd, yyyy-mm-dd, ...) - voliteľné",
|
||||
"date_format": "Formát data(see http://strftime.org/)"
|
||||
}
|
||||
},
|
||||
"annual_group": {
|
||||
"title": "Garbage Collection - Ďalšie parametre",
|
||||
"description": "Zadej dátum zvozu (napr. 11/20 pre 20. november)",
|
||||
"data": {
|
||||
"date": "Dátum (mm/dd)",
|
||||
"entities": "Zoznam entít (oddelené čiarkou)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Dny svozu",
|
||||
"description": "Vyber jeden alebo viacej dní zvozu. Viac na: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"collection_days_mon": "Pondelok",
|
||||
"collection_days_tue": "Útorok",
|
||||
"collection_days_wed": "Streda",
|
||||
"collection_days_thu": "Štvrtok",
|
||||
"collection_days_fri": "Piatok",
|
||||
"collection_days_sat": "Sobota",
|
||||
"collection_days_sun": "Nedeľa",
|
||||
"force_week_order_numbers": "Číslo týždňa v mesiaci namiesto čísla dňa"
|
||||
}
|
||||
},
|
||||
"final": {
|
||||
"title": "Garbage Collection - Ďalšie parametre",
|
||||
"description": "Pridané a zakázané dátumy sú zoznamy dátumov vo formáte yyyy-mm-dd, oddelených čiarkou. Viac info na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"first_month": "Prvý mesiac zvozu",
|
||||
"last_month": "Posledný mesiac zvozu",
|
||||
"period": "Perióda (zvoz každých n týždňov/dní): (1-1000)",
|
||||
"first_week": "Prvý týždeň zvozu (1-52)",
|
||||
"first_date": "Prvý dátum",
|
||||
"weekday_order_number_1": "Prvý deň v mesiaci",
|
||||
"weekday_order_number_2": "Druhý deň v mesiaci",
|
||||
"weekday_order_number_3": "Tretí deň v mesiaci",
|
||||
"weekday_order_number_4": "Štvrtý deň v mesiaci",
|
||||
"weekday_order_number_5": "Piaty deň v mesiaci",
|
||||
"week_order_number_1": "Prvý týžden v mesiaci",
|
||||
"week_order_number_2": "Druhý týžden v mesiaci",
|
||||
"week_order_number_3": "Tretí týžden v mesiaci",
|
||||
"week_order_number_4": "Štvrtý týžden v mesiaci",
|
||||
"week_order_number_5": "Piaty týžden v mesiaci",
|
||||
"move_country_holidays": "Štátne sviatky - krajiny (voliteľné)",
|
||||
"holiday_move_offset": "Posunúť sviatok o (dní: -7..7)",
|
||||
"holiday_pop_named": "Ignorovať sviatky (volitelné)",
|
||||
"holiday_in_week_move": "Posunúť na ďalší deň ak je dovolenka v týždni (voliteľné)",
|
||||
"prov": "Štátne sviatky - provincie (volitelné)",
|
||||
"state": "Štátne sviatky - štát (volitelné)",
|
||||
"observed": "Štátne sviatky - sledované (volitelné)"
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Chybná hodnota. Skontroluj zadané hodnoty!",
|
||||
"icon": "Ikony musia býť zadané vo formáte 'prefix:meno'.",
|
||||
"days": "Vyber jeden nebo viacej dní!",
|
||||
"entities": "Entita neexistuje!",
|
||||
"month_day": "Zlý formát dátumu!",
|
||||
"time": "Zlý formát času!",
|
||||
"weekday_order_number": "Vyber jeden nebo viacej dní!",
|
||||
"week_order_number": "Vyber jeden nebo viacej týždňov!",
|
||||
"period": "Perióda musí být číslo medzi 1 a 1000",
|
||||
"first_week": "Prvý týždeň musí být číslo medzi 1 a 52",
|
||||
"date": "Zlý formát dátumu!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Je povolená iba jedna konfigurácia Garbage Collection."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Garbage Collection - Nastavenia",
|
||||
"description": "Zadaj meno senzora a nastav parametre. Viac na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Skryť v kalendári",
|
||||
"frequency": "Frekvencia",
|
||||
"icon_normal": "Ikona (mdi:trash-can)",
|
||||
"icon_tomorrow": "Ikona zvoz zajtra (mdi:delete-restore)",
|
||||
"icon_today": "Ikona zvoz dnes (mdi:delete-circle)",
|
||||
"offset": "Odsadit (medzi -31 a 31 dny)",
|
||||
"expire_after": "Čas expirácie (HH:MM)",
|
||||
"verbose_state": "Verbose state (popis miesto čísiel)",
|
||||
"verbose_format": "Verbose format (Použi `date` a `days` premenné (v zložených zátvorkách))",
|
||||
"include_dates": "Pridané dátumy (yyyy-mm-dd, yyyy-mm-dd, ...) - voliteľné",
|
||||
"exclude_dates": "Zakázané dátumy (yyyy-mm-dd, yyyy-mm-dd, ...) - voliteľné",
|
||||
"date_format": "Formát dátumu(see http://strftime.org/)"
|
||||
}
|
||||
},
|
||||
"annual_group": {
|
||||
"title": "Garbage Collection - Ďalšie parametre",
|
||||
"description": "Zadej dátum zvozu (napr. 11/20 pre 20. november)",
|
||||
"data": {
|
||||
"date": "Dátum (mm/dd)",
|
||||
"entities": "Zoznam entít (oddelené čiarkou)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Garbage Collection - Dni zvozu",
|
||||
"description": "Vyber jeden alebo viac dní zvozu. Více na: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"collection_days_mon": "Pondelok",
|
||||
"collection_days_tue": "Útorok",
|
||||
"collection_days_wed": "Streda",
|
||||
"collection_days_thu": "Štvrtok",
|
||||
"collection_days_fri": "Piatok",
|
||||
"collection_days_sat": "Sobota",
|
||||
"collection_days_sun": "Nedeľa",
|
||||
"force_week_order_numbers": "Číslo týždna v mesiaci namiesto čísla dňa"
|
||||
|
||||
}
|
||||
},
|
||||
"final": {
|
||||
"title": "Garbage Collection - Ďalšie parametre",
|
||||
"description": "Pridané a zakázané dátumy sú zoznamy dátumov vo formáte yyyy-mm-dd, oddelených čiarkou. Viac info na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"first_month": "Prvý mesiac zvozu",
|
||||
"last_month": "Posledný mesiac zvozu",
|
||||
"period": "Perióda (zvoz každých n týždňov/dní): (1-1000)",
|
||||
"first_week": "Prvý týždeň zvozu (1-52)",
|
||||
"first_date": "Prvý dátum",
|
||||
"weekday_order_number_1": "Prvý deň v mesiaci",
|
||||
"weekday_order_number_2": "Druhý deň v mesiaci",
|
||||
"weekday_order_number_3": "Tretí deň v mesiaci",
|
||||
"weekday_order_number_4": "Štvrtý deň v mesiaci",
|
||||
"weekday_order_number_5": "Piaty deň v mesiaci",
|
||||
"week_order_number_1": "Prvý týžden v mesiaci",
|
||||
"week_order_number_2": "Druhý týžden v mesiaci",
|
||||
"week_order_number_3": "Tretí týžden v mesiaci",
|
||||
"week_order_number_4": "Štvrtý týžden v mesiaci",
|
||||
"week_order_number_5": "Piaty týžden v mesiaci",
|
||||
"move_country_holidays": "Štátne sviatky - krajiny (voliteľné)",
|
||||
"holiday_move_offset": "Posunúť sviatok o (dní: -7..7)",
|
||||
"holiday_pop_named": "Ignorovať sviatky (volitelné)",
|
||||
"holiday_in_week_move": "Posunúť na ďalší deň ak je dovolenka v týždni (voliteľné)",
|
||||
"prov": "Štátne sviatky - provincie (volitelné)",
|
||||
"state": "Štátne sviatky - štát (volitelné)",
|
||||
"observed": "Štátne sviatky - sledované (volitelné)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Chybná hodnota. Skontroluj zadané hodnoty!",
|
||||
"icon": "Ikony musia býť zadané vo formáte 'prefix:meno'.",
|
||||
"days": "Vyber jeden nebo viacej dní!",
|
||||
"entities": "Entita neexistuje!",
|
||||
"month_day": "Zlý formát dátumu!",
|
||||
"time": "Zlý formát času!",
|
||||
"weekday_order_number": "Vyber jeden nebo viacej dní!",
|
||||
"week_order_number": "Vyber jeden nebo viacej týždňov!",
|
||||
"period": "Perióda musí být číslo medzi 1 a 1000",
|
||||
"first_week": "Prvý týždeň musí být číslo medzi 1 a 52",
|
||||
"date": "Zlý formát dátumu!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Odvoz odpadkov - Pogostost odvoza",
|
||||
"description": "Vpišite ime senzorja in nastavite parametre. Več informacij na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"name": "Prijazno ime",
|
||||
"hidden": "Skrij v koledarju",
|
||||
"frequency": "Pogostost",
|
||||
"manual_update": "Stanje senzorja se posodablja ročno s klicem storitve",
|
||||
"icon_normal": "Ikona (mdi:trash-can) - opcijsko",
|
||||
"icon_tomorrow": "Ikona pobiranja jutri (mdi:delete-restore) - opcijsko",
|
||||
"icon_today": "Ikona pobiranja danes (mdi:delete-circle) - opcijsko",
|
||||
"offset": "Zamik (med -31 in 31 dni)",
|
||||
"expire_after": "Poteče po (HH:MM) - opcijsko",
|
||||
"verbose_state": "Verbose stanje (tekst namesto številk)",
|
||||
"verbose_format": "Verbose format (uporaba spremenljivk `datum` in `dni` (v oglatih oklepajih))",
|
||||
"include_dates": "Vključi datume (yyyy-mm-dd, yyyy-mm-dd, ...) - opcijsko",
|
||||
"exclude_dates": "Izključi datume (yyyy-mm-dd, yyyy-mm-dd, ...) - opcijsko",
|
||||
"date_format": "Format datuma (glej http://strftime.org/)"
|
||||
}
|
||||
},
|
||||
"annual_group": {
|
||||
"title": "Odvoz odpadkov - Dodatni parametri",
|
||||
"description": "Vpišite datum odvoza (npr. 11/20 za 20.November)",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Seznam vpisov (ločeno z vejico)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Odvoz odpadkov - Collection days",
|
||||
"description": "Izberite enega ali več dni odvoza. Več podrobnosti tukaj: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"collection_days_mon": "Ponedeljek",
|
||||
"collection_days_tue": "Torek",
|
||||
"collection_days_wed": "Sreda",
|
||||
"collection_days_thu": "Četrtek",
|
||||
"collection_days_fri": "Petek",
|
||||
"collection_days_sat": "Sobota",
|
||||
"collection_days_sun": "Nedelja",
|
||||
"force_week_order_numbers": "Naročilo odvoza v tednu meseca namesto v dnevu tedna"
|
||||
}
|
||||
},
|
||||
"final": {
|
||||
"title": "Odvoz odpadkov - Dodatni parametri",
|
||||
"description": "Vključeni in izključeni datumi so seznami datumov, ločeni z vejico v formatu yyyy-mm-dd. Podrobnosti na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"first_month": "Prvi mesec odvoza",
|
||||
"last_month": "Zadnji mesec odvoza",
|
||||
"period": "Odvoz vsakih v tednov/dni: (1-1000)",
|
||||
"first_week": "Prvi teden odvoza (1-52)",
|
||||
"first_date": "Prvi datum",
|
||||
"weekday_order_number_1": "1. dan tedna v mesecu",
|
||||
"weekday_order_number_2": "2. dan tedna v mesecu",
|
||||
"weekday_order_number_3": "3. dan tedna v mesecu",
|
||||
"weekday_order_number_4": "4. dan tedna v mesecu",
|
||||
"weekday_order_number_5": "5. dan tedna v mesecu",
|
||||
"week_order_number_1": "1. teden v mesecu",
|
||||
"week_order_number_2": "2. teden v mesecu",
|
||||
"week_order_number_3": "3. teden v mesecu",
|
||||
"week_order_number_4": "4. teden v mesecu",
|
||||
"week_order_number_5": "5. teden v mesecu",
|
||||
"move_country_holidays": "Premakni na naslednji dan, če je praznik (opcijsko)",
|
||||
"holiday_move_offset": "Premakni praznike za # dni(-7..7)",
|
||||
"holiday_pop_named": "Ignoriraj praznike (seznam) - opcijsko",
|
||||
"holiday_in_week_move": "Premakni na naslednji dan, če je praznik v tednu (opcijsko)",
|
||||
"prov": "Državni prazniki - provincialni (opcijsko)",
|
||||
"state": "Državni prazniki - državni (opcijsko)",
|
||||
"observed": "Državni prazniki - premični (opcijsko)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Neveljavna vrednost. Prosim, preverite vaš vnos!",
|
||||
"icon": "Ikone morajo biti vpisane v formatu 'predpona:ime'.",
|
||||
"days": "Iizberite enega ali več dni!",
|
||||
"entities": "Entiteta ne obstaja!",
|
||||
"month_day": "Neveljaven format datuma!",
|
||||
"time": "Neveljaven format časa!",
|
||||
"weekday_order_number": "Izberite enega ali več dni",
|
||||
"week_order_number": "Izberite enega ali več tednov",
|
||||
"period": "Interval mora biti številka med 1 in 1000",
|
||||
"first_week": "Prvi teden mora biti številka med 1 in 52",
|
||||
"date": "Neveljaven format datuma!"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "Dovoljena je samo ena konfiguracija odvoza odpadkov."
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Odvoz odpadkov - Pogostost odvoza",
|
||||
"description": "Spremenite parametre. Več informacij: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"hidden": "Skrij v koledarju",
|
||||
"frequency": "Pogostost",
|
||||
"manual_update": "Stanje senzorja se posodablja ročno s klicanjem storitve",
|
||||
"icon_normal": "Ikona (mdi:trash-can) - opcijsko",
|
||||
"icon_tomorrow": "Ikona codvoz jutri (mdi:delete-restore) - opcijsko",
|
||||
"icon_today": "Ikona odvoz danes (mdi:delete-circle) - opcijsko",
|
||||
"offset": "Zamik (med -31 in 31 dni)",
|
||||
"expire_after": "Expire after (HH:MM) - opcijsko",
|
||||
"verbose_state": "Verbose stanje (tekst namesto številk)",
|
||||
"verbose_format": "Verbose format (uporaba spremenljivk `datum` in `dni` (v oglatih oklepajih))",
|
||||
"include_dates": "Vključi datume (yyyy-mm-dd, yyyy-mm-dd, ...) - opcijsko",
|
||||
"exclude_dates": "Izključi datume (yyyy-mm-dd, yyyy-mm-dd, ...) - opcijsko",
|
||||
"date_format": "Format datume (glej http://strftime.org/)"
|
||||
}
|
||||
},
|
||||
"annual_group": {
|
||||
"title": "Odvoz odpadkov - Dodatni parametri",
|
||||
"description": "Vpišite datum dneva odvoza (npr. 11/20 za 20.November)",
|
||||
"data": {
|
||||
"date": "Datum (mm/dd)",
|
||||
"entities": "Seznam entitet (ločenih z vejivo)"
|
||||
}
|
||||
},
|
||||
"detail": {
|
||||
"title": "Odvoz odpadkov - Collection days",
|
||||
"description": "Izberite enega ali več dni odvoza. Več informacij tukaj: https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"collection_days_mon": "Ponedeljek",
|
||||
"collection_days_tue": "Torek",
|
||||
"collection_days_wed": "Sreda",
|
||||
"collection_days_thu": "Četrtek",
|
||||
"collection_days_fri": "Petek",
|
||||
"collection_days_sat": "Sobota",
|
||||
"collection_days_sun": "Nedelja",
|
||||
"force_week_order_numbers": "Naročilo odvoza v tednu meseca namesto v dnevu tedna"
|
||||
}
|
||||
},
|
||||
"final": {
|
||||
"title": "Odvoz odpadkov - Dodatni parametri",
|
||||
"description": "Vključeni in izključeni datumi so seznami datumov, ločeni z vejico v formatu yyyy-mm-dd. Podrobnosti na https://github.com/bruxy70/Garbage-Collection",
|
||||
"data": {
|
||||
"first_month": "Prvi mesec odvoza",
|
||||
"last_month": "Zdnji mesec odvoza",
|
||||
"period": "Odvoz vsakih n tednov/dni: (1-1000)",
|
||||
"first_week": "Prvi teden odvoza (1-52)",
|
||||
"first_date": "Prvi datum",
|
||||
"weekday_order_number_1": "1. dan tedna v mesecu",
|
||||
"weekday_order_number_2": "2. dan tedna v mesecu",
|
||||
"weekday_order_number_3": "3. dan tedna v mesecu",
|
||||
"weekday_order_number_4": "4. dan tedna v mesecu",
|
||||
"weekday_order_number_5": "5. dan tedna v mesecu",
|
||||
"week_order_number_1": "1. teden v mesecu",
|
||||
"week_order_number_2": "2. teden v mesecu",
|
||||
"week_order_number_3": "3. teden v mesecu",
|
||||
"week_order_number_4": "4. teden v mesecu",
|
||||
"week_order_number_5": "5. teden v mesecu",
|
||||
"move_country_holidays": "Premakni praznik na naslednji dan (opcijsko)",
|
||||
"holiday_move_offset": "Premakni praznike za # dni(-7..7)",
|
||||
"holiday_pop_named": "Ignoriraj praznike (seznam) - opcijsko",
|
||||
"holiday_in_week_move": "Premakni na naslednji dan, če je praznik v tednu (opcijsko)",
|
||||
"prov": "Državni prazniki - provincialni (opcijsko)",
|
||||
"state": "Državni prazniki- državni (opcijsko)",
|
||||
"observed": "Državni prazniki - premični (opcijsko)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"value": "Neveljavna vrednost. Prosim, preverite vaš vnos!",
|
||||
"icon": "Ikona mora biti vpisana v formatu 'predpona:ime'.",
|
||||
"days": "Izberite enega ali več dni!",
|
||||
"entities": "Entiteta ne obstaja!",
|
||||
"month_day": "Neveljaven format datuma!",
|
||||
"time": "Neveljaven format časa!",
|
||||
"weekday_order_number": "Izberite enega ali več dni",
|
||||
"week_order_number": "Izberite enega ali več tednov",
|
||||
"period": "Interval mora biti številka med 1 in 1000",
|
||||
"first_week": "Prvi teden mora biti številka med 1 in 52",
|
||||
"date": "Neveljaven format datuma!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user