├── .github ├── FUNDING.yml └── workflows │ ├── automerge.yaml │ ├── hacs.yaml │ ├── hassfest.yaml │ └── release.yaml ├── LICENSE ├── README.md ├── custom_components └── custom_templates │ ├── __init__.py │ ├── const.py │ ├── manifest.json │ └── templates │ ├── __init__.py │ ├── all_translations.py │ ├── dict_merge.py │ ├── eval_template.py │ ├── is_available.py │ ├── state_attr_translated.py │ ├── state_translated.py │ ├── translatable_template.py │ ├── translated.py │ └── utils.py └── hacs.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: piotrmachowski 2 | custom: ["buycoffee.to/piotrmachowski", "paypal.me/PiMachowski", "revolut.me/314ma"] 3 | -------------------------------------------------------------------------------- /.github/workflows/automerge.yaml: -------------------------------------------------------------------------------- 1 | name: 'Automatically merge master -> dev' 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | name: Automatically merge master to dev 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | name: Git checkout 15 | with: 16 | fetch-depth: 0 17 | - name: Merge master -> dev 18 | run: | 19 | git config user.name "GitHub Actions" 20 | git config user.email "PiotrMachowski@users.noreply.github.com" 21 | if (git checkout dev) 22 | then 23 | git merge --ff-only master || git merge --no-commit master 24 | git commit -m "Automatically merge master -> dev" || echo "No commit needed" 25 | git push origin dev 26 | else 27 | echo "No dev branch" 28 | fi -------------------------------------------------------------------------------- /.github/workflows/hacs.yaml: -------------------------------------------------------------------------------- 1 | name: Validate HACS 2 | on: 3 | push: 4 | pull_request: 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | name: Download repo 11 | with: 12 | fetch-depth: 0 13 | 14 | - uses: actions/setup-python@v2 15 | name: Setup Python 16 | with: 17 | python-version: '3.10.x' 18 | 19 | - uses: actions/cache@v2 20 | name: Cache 21 | with: 22 | path: | 23 | ~/.cache/pip 24 | key: custom-component-ci 25 | 26 | - name: HACS Action 27 | uses: hacs/action@main 28 | with: 29 | category: integration 30 | -------------------------------------------------------------------------------- /.github/workflows/hassfest.yaml: -------------------------------------------------------------------------------- 1 | name: Validate with hassfest 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | validate: 9 | runs-on: "ubuntu-latest" 10 | steps: 11 | - uses: "actions/checkout@v2" 12 | - uses: home-assistant/actions/hassfest@master 13 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | release: 9 | name: Prepare release 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Download repo 13 | uses: actions/checkout@v1 14 | 15 | - name: Zip custom_templates dir 16 | run: | 17 | cd /home/runner/work/Home-Assistant-custom-components-Custom-Templates/Home-Assistant-custom-components-Custom-Templates/custom_components/custom_templates 18 | zip custom_templates.zip -r ./ 19 | 20 | - name: Upload zip to release 21 | uses: svenstaro/upload-release-action@v1-release 22 | with: 23 | repo_token: ${{ secrets.GITHUB_TOKEN }} 24 | file: /home/runner/work/Home-Assistant-custom-components-Custom-Templates/Home-Assistant-custom-components-Custom-Templates/custom_components/custom_templates/custom_templates.zip 25 | asset_name: custom_templates.zip 26 | tag: ${{ github.ref }} 27 | overwrite: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Piotr Machowski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![HACS Default][hacs_shield]][hacs] 2 | [![GitHub Latest Release][releases_shield]][latest_release] 3 | [![GitHub All Releases][downloads_total_shield]][releases] 4 | [![Installations][installations_shield]][releases] 5 | [![Community Forum][community_forum_shield]][community_forum] 6 | [![Ko-Fi][ko_fi_shield]][ko_fi] 7 | [![buycoffee.to][buycoffee_to_shield]][buycoffee_to] 8 | [![PayPal.Me][paypal_me_shield]][paypal_me] 9 | [![Revolut.Me][revolut_me_shield]][revolut_me] 10 | 11 | 12 | 13 | [hacs_shield]: https://img.shields.io/static/v1.svg?label=HACS&message=Default&style=popout&color=green&labelColor=41bdf5&logo=HomeAssistantCommunityStore&logoColor=white 14 | [hacs]: https://hacs.xyz/docs/default_repositories 15 | 16 | [latest_release]: https://github.com/PiotrMachowski/Home-Assistant-custom-components-Custom-Templates/releases/latest 17 | [releases_shield]: https://img.shields.io/github/release/PiotrMachowski/Home-Assistant-custom-components-Custom-Templates.svg?style=popout 18 | 19 | [releases]: https://github.com/PiotrMachowski/Home-Assistant-custom-components-Custom-Templates/releases 20 | [downloads_total_shield]: https://img.shields.io/github/downloads/PiotrMachowski/Home-Assistant-custom-components-Custom-Templates/total 21 | 22 | [installations_shield]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fanalytics.home-assistant.io%2Fcustom_integrations.json&query=%24.custom_templates.total&style=popout&color=41bdf5&label=analytics 23 | 24 | [community_forum_shield]: https://img.shields.io/static/v1.svg?label=%20&message=Forum&style=popout&color=41bdf5&logo=HomeAssistant&logoColor=white 25 | [community_forum]: https://community.home-assistant.io/t/custom-templates/528378 26 | 27 | 28 | # Custom Templates 29 | 30 | > [!CAUTION] 31 | > This custom integration tampers with internal code of Home Assistant which _might_ cause some unforeseen issues (especially after HA updates). 32 | > 33 | > If you encounter any problems related to templating engine or translations try uninstalling this integration before raising an issue in Home Assistant repository. 34 | 35 | 36 | This integration adds possibility to use new functions in Home Assistant Jinja2 templating engine: 37 | - `ct_state_translated` - returns translated state of an entity 38 | - `ct_state_attr_translated` - returns translated value of an attribute of an entity 39 | - `ct_translated` - returns translation for a given key 40 | - `ct_all_translations` - returns all available translations (that can be used with `ct_translated`) 41 | - `ct_eval` - evaluates text as a template 42 | - `ct_is_available` - checks if given entity is available 43 | - `ct_dict_merge` - Merges two or more dictionaries together. 44 | 45 | ## Usage 46 | 47 | ### `ct_state_translated` 48 | 49 | This function returns translated state of an entity. 50 | Second parameter (language) is optional - it defaults to the language configured in Home Assistant. 51 | 52 |
55 | Input 56 | | 57 |58 | Output 59 | | 60 |
---|---|
63 | 64 | ``` 65 | State: {{ states("sun.sun") }} 66 | Translated en: {{ ct_state_translated("sun.sun", "en") }} 67 | Translated en: {{ "sun.sun" | ct_state_translated("en") }} 68 | Translated nl: {{ ct_state_translated("sun.sun", "nl") }} 69 | Translated nl: {{ "sun.sun" | ct_state_translated("nl") }} 70 | ``` 71 | 72 | | 73 |74 | 75 | ``` 76 | State: below_horizon 77 | Translated en: Below horizon 78 | Translated en: Below horizon 79 | Translated nl: Onder de horizon 80 | Translated nl: Onder de horizon 81 | ``` 82 | 83 | | 84 |
95 | Input 96 | | 97 |98 | Output 99 | | 100 |
---|---|
103 | 104 | ``` 105 | Attribute: {{ state_attr("automation.example", "mode") }} 106 | Translated en: {{ ct_state_attr_translated("automation.example", "mode", "en") }} 107 | Translated en: {{ "automation.example" | ct_state_attr_translated("mode", "en") }} 108 | Translated nl: {{ ct_state_attr_translated("automation.example", "mode", "nl") }} 109 | Translated nl: {{ "automation.example" | ct_state_attr_translated("mode", "nl") }} 110 | ``` 111 | 112 | | 113 |114 | 115 | ``` 116 | Attribute: single 117 | Translated en: Single 118 | Translated en: Single 119 | Translated nl: Enkelvoudig 120 | Translated nl: Enkelvoudig 121 | ``` 122 | 123 | | 124 |
135 | Input 136 | | 137 |138 | Output 139 | | 140 |
---|---|
143 | 144 | ```yaml 145 | Translated en: {{ ct_translated("component.sun.entity_component._.state.below_horizon", "en") }} 146 | Translated en: {{ "component.sun.entity_component._.state.below_horizon" | ct_translated("en") }} 147 | Translated nl: {{ ct_translated("component.sun.entity_component._.state.below_horizon", "nl") }} 148 | Translated nl: {{ "component.sun.entity_component._.state.below_horizon" | ct_translated("nl") }} 149 | ``` 150 | 151 | | 152 |153 | 154 | ``` 155 | Translated en: Below horizon 156 | Translated en: Below horizon 157 | Translated nl: Onder de horizon 158 | Translated nl: Onder de horizon 159 | ``` 160 | 161 | | 162 |
173 | Input 174 | | 175 |176 | Output 177 | | 178 |
---|---|
181 | 182 | ``` 183 | {{ ct_all_translations("en") }} 184 | ``` 185 | 186 | | 187 |188 | 189 | ```json 190 | { 191 | "component.sun.entity_component._.state.above_horizon": "Above horizon", 192 | "component.sun.entity_component._.state.below_horizon": "Below horizon" 193 | } 194 | ``` 195 | 196 | | 197 |
207 | Input 208 | | 209 |210 | Output 211 | | 212 |
---|---|
215 | 216 | ```yaml 217 | {% set template_text = "{{ states('sun.sun') }}" %} 218 | {{ ct_eval(template_text) }} 219 | {{ template_text | ct_eval }} 220 | ``` 221 | 222 | | 223 |224 | 225 | ``` 226 | below_horizon 227 | below_horizon 228 | ``` 229 | 230 | | 231 |
248 | Input 249 | | 250 |251 | Output 252 | | 253 |
---|---|
256 | 257 | ```yaml 258 | {{ states('sensor.invalid') }} 259 | {{ ct_is_available('sensor.invalid') }} 260 | {{ ct_is_available('sensor.invalid', ['', 'unknown']) }} 261 | ``` 262 | 263 | | 264 |265 | 266 | ``` 267 | unavailable 268 | true 269 | false 270 | ``` 271 | 272 | | 273 |
284 | Input 285 | | 286 |287 | Output 288 | | 289 |
---|---|
292 | 293 | ```yaml 294 | {% set dict_1 = {'a':1,'b':2,'c':3} %} 295 | {% set dict_2 = {'d':4,'e':5,'f':6} %} 296 | {% set dict_3 = {'b':7,'d':8,'g':9} %} 297 | {{ ct_dict_merge(dict_1, dict_1) }} 298 | {{ ct_dict_merge(dict_1, dict_2) }} 299 | {{ ct_dict_merge(dict_2, dict_3) }} 300 | {{ ct_dict_merge(dict_1, dict_2, dict_3) }} 301 | ``` 302 | 303 | | 304 |305 | 306 | ```django 307 | 308 | 309 | 310 | {'a': 1, 'b': 2, 'c': 3} 311 | {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6} 312 | {'d': 8, 'e': 5, 'f': 6, 'b': 7, 'g': 9} 313 | {'a': 1, 'b': 7, 'c': 3, 'd': 8, 'e': 5, 'f': 6, 'g': 9} 314 | ``` 315 | 316 | | 317 |
Platform | 375 |Payment methods | 376 |Link | 377 |Comment | 378 |
---|---|---|---|
Ko-fi | 381 |
382 | |
385 |
386 | ![]() |
388 |
389 | |
392 |
buycoffee.to | 395 |
396 | |
399 |
400 | |
402 | 403 | |
PayPal | 406 |
407 | |
409 |
410 | ![]() |
412 |
413 | |
415 |
Revolut | 418 |
419 | |
422 |
423 | ![]() |
425 |
426 | |
428 |