diff --git a/blog/2024-01-19-icon-translations.md b/blog/2024-01-19-icon-translations.md
new file mode 100644
index 00000000..b8678c48
--- /dev/null
+++ b/blog/2024-01-19-icon-translations.md
@@ -0,0 +1,37 @@
+---
+author: Franck Nijhof
+authorURL: https://twitter.com/frenck
+authorImageURL: /img/profile/frenck.png
+authorTwitter: frenck
+title: Icon translations
+---
+
+In Home Assistant 2024.2, we will introduce a new way to provide icons for integrations: Icon translations.
+
+Icon translations work similarly to our regular translations for entities, which can translate the state of an entity or entity attribute state into any language. Icon translations work in a similar way, but instead of translating the state into the end-user language, it translates the state into an icon.
+
+Each integration can now provide an `icons.json` file, containing a mapping of states to icons. Here is an example of a Moon `sensor` entity that provides different icons for each state:
+
+```json
+{
+ "entity": {
+ "sensor": {
+ "phase": {
+ "default": "mdi:moon",
+ "state": {
+ "new_moon": "mdi:moon-new",
+ "first_quarter": "mdi:moon-first-quarter",
+ "full_moon": "mdi:moon-full",
+ "last_quarter": "mdi:moon-last-quarter"
+ }
+ }
+ }
+ }
+}
+```
+
+Icon translations also support translating entity attribute states.
+
+[Read more about icon translations in our documentation](/docs/core/entity#icons).
+
+This change is backward-compatible. The existing `icon` property of entities will continue to work as it did before. However, we recommend the use of the icon translation over the `icon` property.
diff --git a/docs/core/entity.md b/docs/core/entity.md
index f23a98a8..78bb346c 100644
--- a/docs/core/entity.md
+++ b/docs/core/entity.md
@@ -82,7 +82,7 @@ To avoid calculations in a property method, set the corresponding [entity class
| should_poll | `bool` | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](integration_fetching_data.md#push-vs-poll).
| state | str | int | float | None
| `None` | The state of the entity. In most cases this is implemented by the domain base entity and should not be implemented by integrations.
| supported_features | int | None
| `None` | Flag features supported by the entity. Domains specify their own.
-| translation_key | str | None
| `None` | A key for looking up translations of the entity's state in [`entity` section of the integration's `strings.json`](/docs/internationalization/core#state-of-entities).
+| translation_key | str | None
| `None` | A key for looking up translations of the entity's state in [`entity` section of the integration's `strings.json`](/docs/internationalization/core#state-of-entities) and for translating the state into an matching [icon](#icons). |
| translation_placeholders | dict | None
| `None` | Placeholder definitions for [translated entity name](/docs/internationalization/core/#name-of-entities).
:::warning
@@ -115,7 +115,7 @@ The following properties are also available on entities. However, they are for a
| ------------------------------- | ---------------------------- | ------- | -----------
| capability_attributes | dict | None
| `None` | State attributes which are stored in the entity registry. This property is implemented by the domain base entity and should not be implemented by integrations.
| force_update | `bool` | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. |
-| icon | str | None
| `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all entities according to its `device_class`. This should be used only in the case where there either is no matching `device_class` or where the icon used for the `device_class` would be confusing or misleading. |
+| icon | str | None
| `None` | Icon to use in the frontend. Using this property is no recommended. [More information about using icons](#icons). |
| state_attributes | dict | None
| `None` | State attributes of a base domain. This property is implemented by the domain base entity and should not be implemented by integrations.
| unit_of_measurement | str | None
| The unit of measurement that the entity's state is expressed in. In most cases, for example for the `number` and `sensor` domains, this is implemented by the domain base entity and should not be implemented by integrations.
@@ -376,6 +376,85 @@ Called when an entity has their entity_id and hass object assigned, before it is
Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates.
+## Icons
+
+Every entity in Home Assistant has an icon, which is used as a visual indicator to identify the entity more easily in the frontend. Home Assistant uses the [Material Design Icons](https://materialdesignicons.com/) icon set.
+
+In most cases, Home Assistant will pick an icon automatically based on the entity's domain, `device_class`, and `state`. It is preferred to use the default icon if possible, to provide a consistent experience and to avoid confusion for the user. However, it is possible to override provide a custom icon for an entity.
+
+Regardless of the provided icon, it is always possible for the user to customize the icon to their liking in the frontend.
+
+There are two ways to provide a custom icon for an entity, either by providing icon translations or by providing an icon identifier.
+
+### Icon translations
+
+This is the preferred and most modern way to provide a custom icon for an entity. Icon translations work similarly [our regular translations](/docs/internationalization/core#state-of-entities), but instead of translating the state of an entity, they translate the states of an entity to icons.
+
+The `translation_key` property of an entity defines the icon translation to use. This property is used to look up the translation in the `entity` section of the integration's `icons.json` file.
+
+To differentiate entities and their translations, provide different translation keys. The following example `icons` for a Moon domain `sensor` entity with its `translation_key` property set to phase:
+
+```json
+{
+ "entity": {
+ "sensor": {
+ "phase": {
+ "default": "mdi:moon",
+ "state": {
+ "new_moon": "mdi:moon-new",
+ "first_quarter": "mdi:moon-first-quarter",
+ "full_moon": "mdi:moon-full",
+ "last_quarter": "mdi:moon-last-quarter"
+ }
+ }
+ }
+ }
+}
+```
+
+Notice that icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). The `default` icon is used when the entity's state is not in the `state` section. The `state` section is optional, and if not provided, the `default` icon will be used for all states.
+
+Icons for entity state attributes can also be provided. The following example provides icons for a `climate` entity with its `translation_key` property set to `ubercool`. This entity has a `preset_mode` state attribute, which can be set to `vacation` or `night`. The frontend will use these in, for example, the climate card.
+
+```json
+{
+ "entity": {
+ "climate": {
+ "ubercool": {
+ "state_attributes": {
+ "preset_mode": {
+ "default": "mdi:confused",
+ "state": {
+ "vacation": "mdi:umbrella-beach",
+ "night": "mdi:weather-night"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+### Icon property
+
+Another way to provide an icon for an entity is by setting the `icon` property of an entity, which returns a string referencing the `mdi` icon. As this property is a method, it is possible to return different icons based on custom logic. For example, it could be possible to return different icons based on something that is not part of the entity's state.
+
+```python
+class MySwitch(SwitchEntity):
+
+ @property
+ def icon(self) -> str | None:
+ """Icon of the entity, based on time."""
+ if now().hour < 12:
+ return "mdi:weather-night"
+ return "mdi:weather-sunny"
+
+ ...
+```
+
+It is not possible to provide icons for state attributes using the `icon` property. Please note that using the `icon` property is discouraged; using the above-mentioned icon translations is preferred.
+
## Excluding state attributes from recorder history
State attributes which are not suitable for state history recording should be excluded from state history recording by including them in either of `_entity_component_unrecorded_attributes` or `_unrecorded_attributes`.