Commit graph

614 commits

Author SHA1 Message Date
Bas Nijholt
4054757a1b Include reviewed autoreset fix in prerelease preview 2026-09-06 01:39:25 -07:00
Bas Nijholt
6eacf31512 Merge verified fixes into prerelease preparation 2026-09-06 01:38:54 -07:00
Bas Nijholt
efa64d01be
fix: allow negative service offsets (#1524) 2026-09-06 10:35:35 +02:00
Bas Nijholt
17d9b39700
fix: restore Czech options placeholders (#1523) 2026-09-06 10:35:30 +02:00
Bas Nijholt
c05587a092 Fix autoreset timeout during partial adaptation 2026-09-06 01:31:45 -07:00
Bas Nijholt
0f606fb935 chore: prepare version 1.32.0b1 2026-09-06 01:30:32 -07:00
proscar87
a2186ecf22
perf: stagger periodic adaptation updates (#1500)
Spread recurring updates with a deterministic per-switch offset while keeping turn-on adaptation immediate. Register the delayed listener on Home Assistant's event loop and cover cancellation, reconfiguration, and cadence with real timer tests.

Closes #939.

Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 01:12:28 -07:00
mueslo
68c0e4db69
fix: preserve Home Assistant area target exclusions (#1511)
* Exclude 'service' lights (entity_category) from area intercept turn-on

Fixes #1510

When Adaptive Lighting intercepts an area/label-targeted light.turn_on, the
intercept rewrites the call to target only the managed lights (see
modify_service_data), so Home Assistant's own handler turns on only those.
AL then re-issues light.turn_on for the remaining 'skipped' (unmanaged)
entities so they still come on.

The problem: HA excludes entities with an entity_category (config/diagnostic,
e.g. the Home Assistant Voice LED ring) from area/label expansion, but AL's
re-issue did not, so AL was the sole thing turning these service lights on.

Changes:
- Keep re-issuing skipped lights so unmanaged normal lights still come on,
  but filter out 'service' lights (entity_category set) from that re-issue.
- Add _is_service_light helper (registry-based) and divert a *managed*
  service light to 'skipped' in _separate_entity_ids, so it is excluded from
  the intercept turn-on while still being adapted when on.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add toggle regression test for service light exclusion from area intercept

Mirrors test_service_light_excluded_from_area_intercept_turn_on but uses
light.toggle: a service light (entity_category set) in an area must remain
off when AL intercepts an area toggle. The managed lights still toggle on.

Refs #1510, PR #1511.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Only exclude service lights from indirect (area/device/label) expansion

Previously _is_service_light filtered service lights unconditionally, which
also excluded a service light explicitly named in `entity_id`. Home
Assistant only excludes such lights from indirect area/device/label expansion
and turns them on when directly targeted, so AL must mirror that: service
lights are now excluded from the intercept/re-issue only when not directly
targeted (`direct_entity_ids`).

Adds a regression test for the direct-target case.

Refs #1510, PR #1511.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Use if/elif/else for indirect service-light exclusion; inline check

Address review: collapse the two separate `if is_service`/"if not
is_service" into an `if/elif/else` chain (ruff PLR5501) and inline the
service check as `self._is_service_light(...) and entity_id not in
direct_entity_ids`, which conceptually is `is_indirect_service`.
Matches HA's indirect-only exclusion and keeps the flow simple.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Filter service lights directly in _get_entity_list expansion

Move service-light filtering to the single expansion site
AdaptiveLightingManager._get_entity_list. Area/device expansion is the
only place where HA excludes entity_category lights, so filtering there
mirrors HA and makes the later direct_entity_ids / skipped_normal guards
unnecessary. Explicit entity_id targets bypass expansion and therefore
still turn on service lights, matching HA.

Fully reverts the direct_entity_ids / skipped_normal addition per review.

---------

Co-authored-by: mueslo <mueslo@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 01:04:50 -07:00
Jared Jensen
e453541a78
feat: expose per-attribute manual-control state (#1469)
Adds two new read-only state attributes on the AdaptiveSwitch entity:

- manual_control_brightness: list of light entity_ids whose brightness
  axis is currently in manual override (i.e. AL is paused for brightness
  on those lights).
- manual_control_color: same, for the color axis.

These mirror the existing 'manual_control' attribute (which is a
union of both axes) but expose the LightControlAttributes bitfield
that AL already tracks internally per-light.

Why: the existing 'manual_control' state attribute and the
adaptive_lighting.manual_control event are useful, but neither lets
a template or dashboard see which axis is paused without subscribing
to events. This is especially important with take_over_control_mode:
pause_changed, where one axis can be manual while the other still
adapts. Now a Lovelace card or template sensor can display
brightness/color manual state directly via state_attr().

Test: extends test_manual_control to assert the new attributes
reflect the bitfield correctly.

No new platform, no breaking changes.

Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 00:59:38 -07:00
Bas Nijholt
cc99067c73
fix: keep adapting during polar night and midnight sun (#1489)
Handle missing polar sunrise and sunset with a shared fallback. Bound offsets between actual solar anchors while preserving the daily lighting cycle and configured time behavior.

Co-authored-by: Oscar Pacheco <oscar@gigadefense.com.mx>
2026-09-06 00:23:21 -07:00
proscar87
55f871fd0c
Adopt has_entity_name to fix duplicated entity ids on HA 2026.4+ (#1499)
* Adopt has_entity_name to fix duplicated entity ids on HA 2026.4+

Since HA core 2026.4 (PR 166246) composes entity names as device name +
entity name, and only strips the device prefix when the entity name
starts with it. Adaptive Lighting's names ('Adaptive Lighting Sleep
Mode: stairs' on device 'Adaptive Lighting: stairs') never match, so
new installs get ids like
switch.adaptive_lighting_stairs_adaptive_lighting_sleep_mode_stairs.

Adopt has_entity_name: the main switch takes the device name
('Adaptive Lighting: <name>'), the simple switches use their role
('Sleep Mode', 'Adapt Brightness', 'Adapt Color'). Unique ids are
unchanged, so existing installs keep their entity ids via the registry.

Fixes #1459

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Test the new entity ids and that existing ones survive

The renamed constants were defined but never asserted, so neither the
fresh-install ids nor the registry-preservation claim were covered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: keep the apply-service test light on

Avoid generating brightness zero in the attribute-change helper, which turns the light off and makes the test depend on the current adaptive brightness.

---------

Co-authored-by: proscar87 <proscar87@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 09:18:49 +02:00
proscar87
67d4a2f657
fix: clamp() collapsed to minimum when min_brightness > max_brightness (#1507)
* fix: clamp() collapsed to minimum when min_brightness > max_brightness

A user can intentionally set min_brightness > max_brightness (or the
equivalent for color temperature) for an inverted timescale -- e.g. a
porch light that should be brighter at night than during the day.
clamp()'s max(minimum, min(value, maximum)) assumed minimum <= maximum;
when inverted, min(value, maximum) is always <= maximum < minimum, so
max(minimum, ...) always returns minimum. linear and tanh brightness
modes -- both of which end in a clamp(brightness, min_brightness,
max_brightness) call -- got stuck returning one fixed value regardless
of the time of day.

Fixes #1421

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* test: accept current Home Assistant brightness validation errors

Keep asserting the maximum brightness limit without depending on the validation library's dictionary-path wording.

---------

Co-authored-by: Oscar Pacheco <proscar@MacBook-Pro-de-Oscar.local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 00:10:21 -07:00
Dennis Dekker
c620d1480a
fix: re-adapt lights right after the auto-reset timer fires (#1506)
When the auto-reset timer fired, its callback called manager.reset(),
which pops the timer and calls timer.cancel() - cancelling the very task
that was running the callback. The manual_control flag was cleared, but
the re-adaptation that should follow was silently cancelled, so the light
only changed on the next interval pass (with the normal transition).

_AsyncSingleShotTimer.cancel() now never cancels the task that is
currently running its own callback. The trailing assert in the callback
is removed because it is reachable now and could trip when a new manual
change comes in while the re-adaptation is still running. The existing
auto-reset test also checks that a light.turn_on with the 'autoreset'
context is sent.

Fixes #1233

Co-authored-by: Dennis-Dekker <>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 07:01:50 +00:00
Samson Brock
68c66a0ff3
Fix options flow changes silently discarded for pre-refactor UI entries (#1504)
* Fix options flow changes being silently discarded for UI-configured entries

validate() merges config_entry.options then config_entry.data, on the
assumption that data only ever holds YAML-imported settings (which should
win) or, for UI-created entries, just the entry name (harmless to apply
last).

That assumption doesn't hold for entries created before data/options were
split: their data still carries the full settings snapshot from initial
setup. Applying it after options means any change made through the options
flow for a key that already exists in data (e.g. adding a light) is
silently ignored, even though the options flow reports success and the
entry reloads without error.

Reproduced on a real entry: added a light via the options flow, entry
reloaded cleanly, but the light was never picked up by the switch's
service-call interceptor ("No switch found for entity_id=...") because
data still held the old light list and clobbered the updated options.

Fix: only let data win over options for genuinely YAML-imported entries
(config_entry.source == SOURCE_IMPORT), matching the existing use of that
check elsewhere in this file. For UI-configured entries, apply options
last so changes made through the options flow actually take effect.

* Add focused tests for the data/options merge order in validate()

Covers both source-specific contracts the merge logic relies on, per
review feedback on this PR:

- SOURCE_USER: options must win over data (this PR's actual fix - proven
  to fail against the pre-fix code, verified locally by reverting
  switch.py and re-running).
- SOURCE_IMPORT: data must keep winning over options (the existing,
  intentional YAML-precedence behavior - unchanged by this PR, verified
  to already pass against the pre-fix code too).

Verified against a real Home Assistant instance's test harness
(pytest-homeassistant-custom-component + the actual installed
homeassistant package), not just reasoned about statically.

---------

Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 00:00:02 -07:00
Corey Peruffo
6d46b82313
fix: use quantization-aware comparison in skip_redundant_commands filter (#1513)
* fix: use quantization-aware comparison in skip_redundant_commands filter

_remove_redundant_attributes() compared target values against light state
with exact equality, but many targets can never round-trip exactly through
a device with coarser resolution:

- brightness: HA's 0-255 scale vs the 0-99 Z-Wave Multilevel Switch scale
  leaves 156 of 255 targets that never converge (e.g. 230 -> 89 -> 229),
- color_temp_kelvin: the kelvin -> mired -> kelvin round trip leaves most
  kelvin targets off by up to ~21 K at 6500 K (e.g. 5500 -> 182 -> 5495).

Such attributes survived the filter and were re-sent every interval
forever, which on larger Z-Wave meshes is enough to jam the controller.

Compare brightness with a tolerance of 2 (the exact worst case of the
0-99 scale) and color temperature in mired space, where devices actually
quantize and where the comparison is exact at every kelvin value. Both
are far below the manual-control detection thresholds
(BRIGHTNESS_CHANGE = 25, COLOR_TEMP_CHANGE = 100), so they cannot mask a
genuine user change.

Fixes #1512

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD

* fix: tolerate one mired to cover both floor- and round-based conversions

The previous exact mired equality assumed round-based kelvin<->mired
conversion, but HA core's color_temperature_kelvin_to_mired() and
color_temperature_mired_to_kelvin() both use math.floor, under which a
target like 5500 K comes back as 5524 K in a different rounded mired
bucket and would never be filtered. Flooring in the comparison instead
would merely flip the failure onto integrations that round.

Comparing with a tolerance of one mired converges for both conversion
schemes (verified by brute force over 1000-10000 K: zero stuck targets
under either pipeline) and can hide at most ~2 mireds, far below the
~5.5 mired just-noticeable difference for color temperature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 06:53:06 +00:00
Bas Nijholt
7afdf5bc5c
Update manifest.json to v1.31.0 (#1486) 2026-07-07 09:38:26 -07:00
Bas Nijholt
3638fb3013
fix: don't cancel adaptation when a light group turns on via a member with a reused context (#1483)
* fix: don't cancel adaptation when a light group turns on via a member with a reused context (#1378)

When a member of a light group is turned on (e.g., by a motion sensor
automation) while the group is off, the group turns on as a side effect,
but Home Assistant may reuse the context of the earlier turn_off call for
the group's state change. just_turned_off() saw matching context IDs and
treated the state change as a polling artifact, cancelling adaptation.

- Check whether the off->on state change comes from a light.turn_on call
  before the matching-context polling-artifact check, so automations that
  turn a light off and back on with a single (automation) context adapt
  correctly.
- For light groups, allow adaptation when a member's turn_on event falls
  between the group's on->off and off->on state changes, bounded on both
  sides so stale member events are never treated as explanatory.
- Document that integration-level groups (e.g., Zigbee2MQTT groups) should
  not be nested inside HA Light Groups managed by Adaptive Lighting.

* fix: time-bound the same-context turn_on check instead of reordering

Address review findings:

- Reordering the turn_on-service check above the matching-context check
  reintroduced stale-event false negatives: turn_on_event entries are never
  cleaned up, so a 'turn_on -> delay -> turn_off(transition)' automation
  (one shared context) would defeat the polling-artifact guard and AL could
  turn a light back on right after it was turned off. Restore main's check
  order and instead add a time-bounded own-turn_on check inside the
  matching-context branch, symmetric with the group-member check. This
  also avoids emitting the 'should not happen' warning for self-context
  polling artifacts.
- Add a regression test for the stale same-context turn_on case.
- Add an end-to-end test driving the event-bus listeners for the #1378
  scenario (group kept in manager.lights, as in the reported setups).
- Docs: drop the inaccurate 'expands only one level deep' claim; explain
  that integration-level groups cannot be expanded and nested groups make
  tracking unpredictable.
2026-07-02 08:08:14 -07:00
Bas Nijholt
d4d3d50ada
fix: replace deprecated get_astral_location with get_astral_observer (#1482)
* fix: replace deprecated get_astral_location with get_astral_observer (#1481)

HA 2026.7 deprecates homeassistant.helpers.sun.get_astral_location
(removal planned for 2027.7) in favor of get_astral_observer, causing a
deprecation warning in the HA logs.

- Switch SunEvents/SunLightSettings from astral.location.Location to
  astral.Observer, using the astral.sun module functions (which return
  UTC times by default, matching the previous local=False calls).
- Use get_astral_observer in switch.py, with a fallback for HA < 2026.7
  that constructs the Observer directly from the HA config.
- Update tests and the webapp simulator accordingly.

* ci: handle removal of requirements_test_all.txt in HA 2026.8 dev

HA core removed requirements_test_all.txt (home-assistant/core#171530),
which made test_dependencies.py crash with FileNotFoundError and broke
the dev pytest job and the Docker builds. Fall back to
requirements_all.txt, which carries the same per-integration
'# homeassistant.components.x' annotations. Also extend the
aiohasupervisor pin lookup in scripts/setup-dependencies accordingly.

* test: support modern template light config for HA 2026.6+

HA 2026.6 removed the legacy `light: platform: template` YAML format
(home-assistant/core#169615), so setup_lights found no template platform
on HA dev and every test using it failed with IndexError. Detect legacy
support at runtime (PLATFORM_SCHEMA presence) and fall back to the
modern `template:` config format. The group platform is set up before
the template integration in the modern path, because setting up
`template` also sets up the `light` domain, which would make a later
async_setup_component(hass, LIGHT_DOMAIN, ...) a no-op.
2026-07-01 23:00:35 -07:00
Florian
830c5589f7
fix: reduce log verbosity for self-triggered off-to-on warning (#1433) (#1434)
* fix: reduce log verbosity for self-triggered off-to-on warning (#1433)

Move full event object dump from warning to debug level in
_off_to_on_state_event_is_from_turn_on() (switch.py:2717).

For lights with large effect_list attributes (e.g. Govee lights
with 130+ effects), the warning dumped the entire Event object
including both old_state and new_state, creating log entries
thousands of characters long.

The warning now logs only entity_id and context.id, while the
full event remains available at debug level for troubleshooting.

Fixes #1433

* fix: correct indentation for _LOGGER.debug block

* fix: correct indentation for _LOGGER.warning and _LOGGER.debug

* fix: remove unintended encoding corruption, keep only log level change

Reset switch.py to main and re-apply only the intended change:
move the full event object from warning to debug level in
_off_to_on_state_event_is_from_turn_on().

Addresses reviewer feedback about unintended Unicode corruption
(→ and ≈ characters were corrupted to mojibake).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Florian Horner <florianhorner@Mac.fritz.box>
Co-authored-by: Bas Nijholt <basnijholt@users.noreply.github.com>
2026-04-24 13:30:18 -07:00
Bas Nijholt
c4b8e28ea8
fix: restore hassfest and Home Assistant CI
## Summary
- fix hassfest validation by replacing raw options-description URLs with Home Assistant translation placeholders
- extend the pytest CI matrix to cover the latest patch release for each Home Assistant month, plus dev
- align CI/dev container Python versions and tests with newer Home Assistant behavior

## Validation
- GitHub Actions pytest matrix passed for 2024.12.5 through 2026.4.3 plus dev
- Docker passed for linux/amd64 and linux/arm64
- hassfest, HACS validation, pre-commit, pre-commit.ci, markdown-code-runner, docs build, and Release Drafter passed
2026-04-24 11:31:53 -07:00
Roee Hendel
6cebe14a69
fix: merge last_service_data across split calls to fix detect_non_ha_changes with separate_turn_on_commands (#1426)
* test: regression test — AL must not override manual brightness with separate_turn_on_commands

End-to-end scenario: user adjusts brightness via a directly-bound Zigbee
switch (e.g. IKEA RODRET).  No HA service call is made; ZHA reports the new
brightness via async_update_entity.  On the next adaptation interval AL must
detect the change and stop overriding the user's brightness.

The test verifies the user-visible symptom: after two adaptation cycles
following a simulated direct-Zigbee brightness change, the light's brightness
must still be the manually set value — not AL's own target.

NOTE: this test FAILS on the current code.  It is committed here to document
the bug before the fix is applied in the next commit.

* fix: merge last_service_data across split calls to fix detect_non_ha_changes with separate_turn_on_commands

When separate_turn_on_commands=True, each adaptation cycle makes two
light.turn_on calls (brightness, then color_temp).  Previously each call
overwrote last_service_data[light], so after the cycle only the color_temp
key remained.  _attributes_have_changed() then saw old_brightness=None and
silently skipped the brightness comparison, so a manually-set brightness was
never detected and AL kept overriding it.

Fix: merge instead of overwrite so all split-call attributes accumulate:

    self.manager.last_service_data[light] = {
        **self.manager.last_service_data.get(light, {}),
        **service_data,
    }

* test: add intermediate assertions to regression test

Two assertions were promised in the PR description but missing:
1. After the force-adapt, assert that last_service_data contains BOTH
   brightness AND color — directly proving the merge fix works.
2. After the first non-forced update, assert that BRIGHTNESS is in
   manual_control — proving detection fired, not just that the final
   state is right.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* refactor: remove spurious comments, trim test docstring and assertions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: strip verbose comments from test, trim assert messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* test: add message to bare assert
2026-03-16 15:54:53 -07:00
Bas Nijholt
f9ccc946ee
Migrate to markdown-code-runner's built-in include_section() (#1417) 2026-01-26 09:01:50 +01:00
Bas Nijholt
cbbcabdd1f
Add documentation site with Zensical framework (#1385)
* Add documentation site with Zensical framework

Create comprehensive documentation site for adaptive-lighting.nijho.lt:

- Add zensical.toml configuration with Material theme (amber/orange)
- Create docs_gen.py module for extracting README sections via markers
- Add section markers to README.md for content reuse
- Create documentation pages:
  - index.md: Home with features overview
  - getting-started.md: Installation and quick setup
  - configuration.md: Auto-generated config options table
  - services.md: Auto-generated service documentation
  - automation-examples.md: Real-world automation recipes
  - troubleshooting.md: Common issues and solutions
  - see-also.md: External resources and links
  - advanced/brightness-modes.md: Brightness mode deep dive
  - advanced/manual-control.md: Manual control system docs
  - advanced/sleep-mode.md: Sleep mode configuration
- Add GitHub Actions workflow for building and deploying to Pages
- Add custom CSS with sun-themed styling
- Add CNAME for custom domain

Uses markdown-code-runner to auto-generate content from code schemas
and extract README sections for single-source documentation.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Remove duplicated content from docs, make pages thin wrappers

- troubleshooting.md: Remove manually written "Additional Tips" section
- automation-examples.md: Remove duplicate "Additional Examples" section
- configuration.md: Remove duplicate "Option Categories" tables
- sleep-mode.md: Simplify to reference main config, remove duplicate examples
- docs_gen.py: Remove unused get_troubleshooting() and get_sleep_mode_intro()

This reduces duplication risk by keeping README as single source of truth.
Docs pages now primarily pull content via markdown-code-runner.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Integrate webapp (simulator) into docs workflow

- Merge deploy-webapp.yml into docs.yml workflow
- Build simulator and place at /simulator/ subdirectory
- Update docs links to use relative paths to simulator
- Remove separate deploy-webapp.yml to avoid conflicts

The combined workflow now:
1. Builds docs with zensical
2. Builds webapp with shinylive
3. Copies webapp to site/simulator/
4. Deploys everything to GitHub Pages

Simulator will be at adaptive-lighting.nijho.lt/simulator/

* Fix pre-commit and CI issues

- Add site_name to zensical.toml (required by MkDocs)
- Fix RET504 in docs_gen.py (unnecessary assignment before return)
- Remove docs/run_markdown_code_runner.py (lint issues, not needed for CI)

* Fix _docs_helpers.py import error in CI

- Add try/except for relative vs absolute imports in _docs_helpers.py
- Remove silent error handling in docs workflow (fail on error)

The relative import fails when markdown-code-runner executes the code
directly via sys.path.insert. The fallback to absolute import fixes this.

* Temporarily enable deployment from feature branch

* Add tabulate dependency for pandas to_markdown()

* Fix theme configuration for proper light/dark mode

- Restructure zensical.toml to match working agent-cli config
- Add three-way palette toggle (system/light/dark)
- Use proper [project.theme] structure
- Simplify extra.css to not override theme colors
- Add Inter font for text, JetBrains Mono for code

* Add Plausible analytics and fix homepage navigation

- Add custom analytics override for plausible.nijho.lt tracking
- Remove hide:navigation from index.md to show menu on homepage

* Remove temporary feature branch deployment settings

Revert to main-only deployment for docs workflow before merging.

* Revert "Remove temporary feature branch deployment settings"

This reverts commit c568694837.

* Add markdown-gfm-admonition for GitHub-style admonitions

The zensical build was failing silently because gfm_admonition extension
was not installed. Add the dependency to pyproject.toml and docs workflow.

* Use uv sync for documentation dependencies

Switch from manual pip installs to uv sync with pyproject.toml for cleaner
dependency management and reproducible builds.

* Fix markdown rendering inside details blocks

Enable md_in_html extension and add markdown="1" attribute to <details>
tags so markdown content inside them is properly rendered.

* Remove emojis from manually written documentation

Keep emojis in auto-generated content from README, but remove from
manually maintained docs in favor of clean text and Material icons.

* Enable attr_list extension for button styling

* Improve pyproject.toml and use GitHub-style admonitions

- Add accurate project metadata (version, authors, classifiers, URLs)
- Organize dependency groups: docs, dev, test
- Add tool configs for ruff, mypy, pytest
- Convert MkDocs-style admonitions (!!! tip) to GitHub-style (> [!TIP])
- Use docs group in CI workflow

* Add homeassistant and ulid-transform as runtime dependencies

Remove speculative test dependencies since tests run inside HA core.

* Simplify docs_gen.py - remove wrapper functions

Use readme_section() directly in docs instead of 10 one-liner wrappers.
Changed default strip_heading to True since that's the common case.

* Populate empty OUTPUT sections with markdown-code-runner

* Add markdown-code-runner workflow for auto-updating docs

- Add docs/run_markdown_code_runner.py script to process all docs
- Add GitHub workflow to run on push/PR and auto-commit changes

* Exclude README.md from markdown-code-runner workflow

README.md contains code blocks that import from
homeassistant.components.adaptive_lighting, which only exists
when running inside Home Assistant core, not in a regular venv.

* Update auto-generated docs

* Use editable install for markdown-code-runner workflow

- Add setuptools.packages.find config pointing to custom_components
- Remove sys.path.insert manipulation from all docs files
- Update imports to use adaptive_lighting.* package paths
- Install package with `uv pip install -e .` in workflow
- Remove deprecated license classifier (PEP 639)

* Consolidate markdown-code-runner into single workflow

- Remove separate markdown-code-runner.yml workflow
- Update update-readme.yml to handle all markdown files (docs + README)
- Rename workflow to "Update auto-generated content"
- Update README imports to use adaptive_lighting package path

* Rename workflow to markdown-code-runner

* Remove accidentally committed files

* Remove redundant markdown-code-runner from docs workflow

* Fix: use uv pip install instead of uv add in CI

* Add webapp deps (astral, shinylive) to docs group

* Remove unused install_dependencies action

* Update to latest action versions (uv@v5, upload-pages-artifact@v4)

* Remove try/except import fallback in _docs_helpers.py

* Restore install_dependencies action (used by pytest)

* Simplify docs workflow: run on all pushes/PRs

* Simplify mcr workflow paths; revert install_dependencies to main

* Remove redundant cp+sed for webapp (file already in repo)

* Fix mcr push: pull --rebase before push

* Fix mcr: checkout PR branch instead of detached HEAD

* Update auto-generated content

* Switch from setuptools to hatch build system

Replace [tool.setuptools.packages.find] with [tool.hatch.build.targets.wheel]
for hatchling compatibility.

* Update auto-generated content

* Move homeassistant deps to docs group

This is a HA custom component, not a pip package. The homeassistant
dependency is only needed for docs building, not as a project dependency.

* Update auto-generated content

* Remove PyPI-only metadata from pyproject.toml

* Remove arbitrary version constraints from dependency groups

* Update auto-generated content

* Remove unused troubleshooting section markers from README

* Remove temporary feature branch settings from docs workflow

* Use GitHub admonition syntax for warning in change_switch_settings section

* Update auto-generated content
2026-01-12 23:39:57 +01:00
Bas Nijholt
e0f812d406
Bump to v1.30.1 (#1384) 2026-01-12 13:46:19 +01:00
Bas Nijholt
e61a018616
Fix regression: lights not adapting when turned on by automation (#1380)
## Summary

- Fixes regression in v1.30.0 where lights turned on by automations were incorrectly marked as "manually controlled"
- Makes `adapt_only_on_bare_turn_on` respect individual attribute tracking from #1356

## Root Cause

PR #1356 added a call to `update_manually_controlled_from_event()` in the `turn_on_off_event_listener.on()` handler for ALL `light.turn_on` events, including when turning a light on from OFF state.

When an automation turns on a light with brightness/color attributes, this incorrectly marked the light as "manually controlled", preventing Adaptive Lighting from adapting it.

## Fix

1. Only call `update_manually_controlled_from_event()` when the light was **already ON** before the turn_on event. Turning on from OFF is handled by `_respond_to_off_to_on_event()`.

2. Make `adapt_only_on_bare_turn_on` respect `take_over_control_mode`:
   - With `PAUSE_CHANGED`: Only pause adaptation of specified attributes, continue adapting unspecified ones
   - With `PAUSE_ALL`: Pause all adaptation (existing behavior)

## Expected Behavior After Fix

| Scenario | `adapt_only_on_bare_turn_on` | `take_over_control_mode` | Result |
|----------|------------------------------|--------------------------|--------|
| Turn on from OFF with brightness | `false` | Either | NOT manually controlled |
| Turn on from OFF with brightness | `true` | `PAUSE_ALL` | All adaptation paused |
| Turn on from OFF with brightness | `true` | `PAUSE_CHANGED` | Only brightness paused, color adapts |
| Turn on from OFF without attributes | Either | Either | NOT manually controlled |
| Change brightness while ON | Either | Either | Brightness manually controlled |

## Test plan

- [x] Turn on light via automation with brightness/color (`adapt_only_on_bare_turn_on=false`) - should adapt
- [x] Turn on light via scene (`adapt_only_on_bare_turn_on=true`, `PAUSE_ALL`) - should pause all adaptation
- [x] Turn on light with brightness only (`adapt_only_on_bare_turn_on=true`, `PAUSE_CHANGED`) - should adapt color
- [x] Both intercept=True and intercept=False paths tested for consistency
- [x] CI tests pass

Fixes #1378

Co-authored-by: Mario Guggenberger <mg@protyposis.net>
2026-01-12 13:40:55 +01:00
Bas Nijholt
f95093e1dc Bump to v1.30.0 2026-01-05 12:43:07 -08:00
Mario Guggenberger
f84ee445b7
Individual manual control of brightness and color (#1356)
* refactor: introduce light control parameter enum

* refactor: replace manual control flag with parameter enum

* test: update deprecated color temp attribute

* build: set execution bits on task scripts

* feat: individual manual control of brightness and color

* test: add tests for individual manual control evaluation

* fix: sequential manual changes not always detected

If multiple attributes of a light were changed within an interval, only the last change was detected because the check in the interval only used the latest event. For example, if there was a brightness change and a following color change, only the color attribute was detected as manually controlled. To fix this, the manual control attribute flags are now set directly from the event handler so that all events are processed.

* fix: invalid service description

* docs: fix missing space in config description

* refactor: pluralize multivalued bitmask enum name
2025-12-22 22:55:16 -08:00
Weblate (bot)
2f599d6e1b
Translations update from Hosted Weblate (#1331)
* Translated using Weblate (German)

Currently translated at 100.0% (156 of 156 strings)

Co-authored-by: Anton <ihrkenntmichnicht@posteo.de>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/de/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Catalan)

Currently translated at 100.0% (156 of 156 strings)

Co-authored-by: Enric Pagès i Gassull <enricpages@hotmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ca/
Translation: Adaptive Lighting/Adaptive Lighting

---------

Co-authored-by: Anton <ihrkenntmichnicht@posteo.de>
Co-authored-by: Enric Pagès i Gassull <enricpages@hotmail.com>
2025-12-12 14:00:30 -08:00
Mario Guggenberger
5886eee04c
Code cleanup (#1348) 2025-12-12 13:37:42 -08:00
Bas Nijholt
94b91a0ddc
fix: use correct entity and context in service interceptor (#1349) 2025-12-12 13:05:01 -08:00
Bas Nijholt
dc61bd191c
Bump to v1.29.0 2025-12-09 23:58:19 -08:00
Bas Nijholt
0180fa4a93
feat: use EntitySelector for light entity selection with search support (#1335)
Replace cv.multi_select with HA's EntitySelector for the lights field
in the options flow. This provides:

- Built-in search/typing to find entities faster
- Better UX with HA's native entity picker
- Improved handling of renamed entities

Closes #1208
2025-12-09 23:51:17 -08:00
edgimar
4aeb50bfe3
feat: add option to duplicate existing lighting instance (#1329)
* feat: add option to duplicate existing lighting instance

A menu step in the config flow was added that allows a user to create a
new instance or duplicate the options of an existing one.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add type annotation, tests, and translations for duplicate feature

- Add type annotation for source_options class attribute
- Add menu step translations to en.json
- Add tests for menu display, new instance creation, and duplication

* Simplify source_options access with class-level default

---------
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2025-12-05 04:15:24 -08:00
Weblate (bot)
2f03e00dc6
Translated using Weblate (Danish) (#1326)
Currently translated at 94.1% (144 of 153 strings)


Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/da/
Translation: Adaptive Lighting/Adaptive Lighting

Co-authored-by: Hans Henrik Juhl <hans@kopula.dk>
2025-11-30 22:53:52 -08:00
Bas Nijholt
80fb93b9f6
Fix propcache dependency (revert to functools) (#1314) 2025-11-28 16:43:52 -08:00
Bas Nijholt
1968e1a9a6
Bump to v1.28.0 (#1310) 2025-11-27 12:42:20 -08:00
Dobby
19d30430bb
Friendly names (#1258) 2025-11-27 12:01:05 -08:00
Weblate (bot)
8ff3babae2
Translations update from Hosted Weblate (#1228)
* Translated using Weblate (Galician)

Currently translated at 50.3% (77 of 153 strings)

Translated using Weblate (Galician)

Currently translated at 49.0% (75 of 153 strings)

Translated using Weblate (Galician)

Currently translated at 46.4% (71 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/gl/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Turkish)

Currently translated at 100.0% (153 of 153 strings)

Added translation using Weblate (Turkish)

Co-authored-by: Furkan Kaya <fkaya.personal@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/tr/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 56.8% (87 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rafael do Amaral Porciuncula <rafael.do.amaralp@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/pt_BR/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Danish)

Currently translated at 90.1% (138 of 153 strings)

Translated using Weblate (Danish)

Currently translated at 88.8% (136 of 153 strings)

Translated using Weblate (Danish)

Currently translated at 88.8% (136 of 153 strings)

Translated using Weblate (Danish)

Currently translated at 88.8% (136 of 153 strings)

Co-authored-by: Emil Friis Osmann <Emilfriisosmann@gmail.com>
Co-authored-by: Hans Henrik Juhl <hans@kopula.dk>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/da/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Russian)

Currently translated at 99.3% (152 of 153 strings)

Co-authored-by: Athish Athish <athisha660@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ru/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Ukrainian)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/uk/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Japanese)

Currently translated at 48.3% (74 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: M.Sugahara <equaaqua@hotmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ja/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: therealmate <hellogaming91@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/hu/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Slovenian)

Currently translated at 71.2% (109 of 153 strings)

Added translation using Weblate (Slovenian)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Tim Music <tim.music98@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/sl/
Translation: Adaptive Lighting/Adaptive Lighting

---------

Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Co-authored-by: Furkan Kaya <fkaya.personal@gmail.com>
Co-authored-by: Rafael do Amaral Porciuncula <rafael.do.amaralp@gmail.com>
Co-authored-by: Emil Friis Osmann <Emilfriisosmann@gmail.com>
Co-authored-by: Hans Henrik Juhl <hans@kopula.dk>
Co-authored-by: Athish Athish <athisha660@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim0@gmail.com>
Co-authored-by: M.Sugahara <equaaqua@hotmail.com>
Co-authored-by: therealmate <hellogaming91@gmail.com>
Co-authored-by: Tim Music <tim.music98@gmail.com>
2025-11-27 10:15:06 -08:00
Bas Nijholt
4feaf2c291
Add bidirectional color mode change detection (issue #1275) (#1299)
Extract _has_color_mode_changed() function that checks original attributes
BEFORE conversion, enabling detection of all mode switches:
- color_temp → RGB ✓
- color_temp → XY ✓
- RGB → color_temp ✓
- RGB → XY ✓
- XY → color_temp ✓
- XY → RGB ✓

This improves on PR #1282 by detecting mode changes in both directions.
2025-11-27 10:02:50 -08:00
DataGhost
afd7b935d7
Check for external light mode (temperature vs rgb) switch (#1282) 2025-11-27 09:54:14 -08:00
ams2990
32719eabae
Fix some type hint issues (#1280) 2025-11-27 09:35:09 -08:00
Bas Nijholt
68e243c87e
Fix infinite loop when disabling SimpleSwitch entities (#1296)
* Add regression tests for SimpleSwitch initial state bug

Adds tests that verify SimpleSwitch._state is set immediately in __init__
rather than waiting for async_added_to_hass(). These tests currently FAIL
because _state is None after __init__, which causes an infinite loop in
_setup_listeners when the entity is disabled (since async_added_to_hass
is never called for disabled entities).

Regression tests for: https://github.com/basnijholt/adaptive-lighting/issues/1264

* Fix infinite loop when disabling SimpleSwitch entities

The issue was that SimpleSwitch._state was initialized to None in __init__,
but only set to a boolean value in async_added_to_hass(). When an entity
is disabled, async_added_to_hass() is never called, so _state stayed None.

The _setup_listeners() method has a while loop that waits for
_state is not None for all SimpleSwitch children (sleep_mode_switch,
adapt_brightness_switch, adapt_color_switch). With _state stuck at None,
this created an infinite loop.

The fix sets _state to initial_state directly in __init__ instead of
waiting for async_added_to_hass() to set it. The async_added_to_hass()
will still properly restore state from the last session or set based
on initial_state as before.

Fixes: https://github.com/basnijholt/adaptive-lighting/issues/1264
2025-11-27 09:30:01 -08:00
Bas Nijholt
6f846c26ca
Fix race condition where timer.start_time is None while is_running() is True (#1295)
When start() creates a task with asyncio.create_task(), the task is scheduled
but not immediately executed. This means is_running() returns True (task exists
and not done), but start_time is still None because _run() hasn't executed yet.

This causes a TypeError when comparing event.time_fired > timer.start_time.

Fix by setting start_time in start() before creating the task.

Fixes #1272
2025-11-27 09:27:13 -08:00
Bas Nijholt
e8af7a485e
Bump to 1.27.0 for fixes in 2025.12 (#1293) 2025-11-27 09:06:41 -08:00
Tom Matheussen
af5a7151aa
Fix HA 2025.12 breaking (#1291) 2025-11-27 08:05:30 -08:00
Bas Nijholt
a8e35ae216
Release v1.26.0 (#1227) 2025-06-15 22:20:53 -07:00
pre-commit-ci[bot]
8035ea3ed1
[pre-commit.ci] pre-commit autoupdate (#1163)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.8.4 → v0.11.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.4...v0.11.13)
- [github.com/psf/black: 24.10.0 → 25.1.0](https://github.com/psf/black/compare/24.10.0...25.1.0)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix pre-commit

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2025-06-15 21:55:36 -07:00
Jeff Wilson
2623aafa61
Remove deprecated @bind_hass (#1207)
* remove @bind_hass decorator

* attempt to pass hass

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2025-06-15 21:47:26 -07:00
Rasmus Lundsgaard
6cb99e80b0
suggested fix for HA2025 deprecation warnings (#1168)
* suggested fix for HA2025 deprecation warnings

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2025-06-15 21:47:06 -07:00
Weblate (bot)
640b634074
Translations update from Hosted Weblate (#1160)
* Translated using Weblate (Galician)

Currently translated at 46.4% (71 of 153 strings)

Translated using Weblate (Galician)

Currently translated at 45.0% (69 of 153 strings)

Added translation using Weblate (Galician)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/gl/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Tamil)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: தமிழ்நேரம் <anishprabu.t@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ta/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Romanian)

Currently translated at 57.5% (88 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: tinutac <tinutac@yahoo.co.uk>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ro/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Ukrainian)

Currently translated at 79.7% (122 of 153 strings)

Translated using Weblate (Ukrainian)

Currently translated at 61.4% (94 of 153 strings)

Translated using Weblate (Ukrainian)

Currently translated at 59.4% (91 of 153 strings)

Translated using Weblate (Ukrainian)

Currently translated at 58.8% (90 of 153 strings)

Co-authored-by: Ada Melentyeva <ada.melentyeva@gmail.com>
Co-authored-by: Artem <artem@molotov.work>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Rostyslav Dudka <rostislav.dudka@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/uk/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Catalan)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Enric Pagès i Gassull <enricpages@hotmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/ca/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Portuguese)

Currently translated at 66.0% (101 of 153 strings)

Co-authored-by: Helder Ferreira <esponjaman@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/pt/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Polish)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Piotr Laszczkowski <swistach@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/pl/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Indonesian)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Reza Almanda <rezaalmanda27@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/id/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Dutch)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: renout <weblate@renout.nl>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/nl/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Spanish)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/es/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (French)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: KosmoMoustache <hosted.weblate.org@kosmo.ovh>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/fr/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Swedish)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/sv/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Finnish)

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ricky Tigg <ricky.tigg@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/fi/
Translation: Adaptive Lighting/Adaptive Lighting

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (153 of 153 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: gmkeebiy <gmkeebiy@sharklasers.com>
Translate-URL: https://hosted.weblate.org/projects/adaptive-lighting/adaptive-lighting/zh_Hans/
Translation: Adaptive Lighting/Adaptive Lighting

---------

Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Co-authored-by: தமிழ்நேரம் <anishprabu.t@gmail.com>
Co-authored-by: tinutac <tinutac@yahoo.co.uk>
Co-authored-by: Ada Melentyeva <ada.melentyeva@gmail.com>
Co-authored-by: Artem <artem@molotov.work>
Co-authored-by: Rostyslav Dudka <rostislav.dudka@gmail.com>
Co-authored-by: Enric Pagès i Gassull <enricpages@hotmail.com>
Co-authored-by: Helder Ferreira <esponjaman@gmail.com>
Co-authored-by: Piotr Laszczkowski <swistach@gmail.com>
Co-authored-by: Reza Almanda <rezaalmanda27@gmail.com>
Co-authored-by: renout <weblate@renout.nl>
Co-authored-by: KosmoMoustache <hosted.weblate.org@kosmo.ovh>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: Ricky Tigg <ricky.tigg@gmail.com>
Co-authored-by: gmkeebiy <gmkeebiy@sharklasers.com>
2025-06-15 21:38:10 -07:00