Compare commits

...

86 Commits

Author SHA1 Message Date
shamoon
8ec488efbd Revert "Fix: subdirectory deployment (#2205)"
This revers commit b8eda91005
2023-10-18 11:44:26 -07:00
shamoon
9e3bc8e64f Update prettier package to v3 2023-10-18 09:49:33 -07:00
shamoon
29827b1c70 Add pre-commit to ci 2023-10-18 09:49:33 -07:00
shamoon
f48cf0dc9f Add instructions to dev docs for pre-commit 2023-10-18 09:49:33 -07:00
shamoon
19c25713c4 Run pre-commit hooks over existing codebase
Co-Authored-By: Ben Phelps <ben@phelps.io>
2023-10-18 09:49:33 -07:00
shamoon
fa50bbad9c Add pre-commit with prettier 2023-10-18 09:49:33 -07:00
Ben Phelps
8e6a169b50 New translations common.json (German) (#2208) 2023-10-18 09:00:58 -07:00
shamoon
4248db7f21 k8s: Support app ingress annotation (#2198) 2023-10-18 08:57:10 -07:00
Isidro Osoria
b8eda91005 Fix: subdirectory deployment (#2205) 2023-10-18 08:49:42 -07:00
Ben Phelps
5f7891d8db New translations common.json (French) (#2206) 2023-10-17 23:29:26 -07:00
Ben Phelps
b14abc2642 New Crowdin updates (#2144)
* New translations common.json (Dutch)

* New translations common.json (Dutch)

* New translations common.json (Polish)

* New translations common.json (Danish)

* New translations common.json (French)

* New translations common.json (German)

* New translations common.json (Chinese Simplified)

* New translations common.json (Chinese Simplified)

* New translations common.json (Dutch)

* New translations common.json (Dutch)

* New translations common.json (German)

* New translations common.json (German)

* New translations common.json (German)

* New translations common.json (Spanish)

* New translations common.json (Danish)

* New translations common.json (Italian)

* New translations common.json (Dutch)

* New translations common.json (Dutch)

* New translations common.json (Japanese)

* New translations common.json (Japanese)
2023-10-17 22:55:01 -07:00
icyleaf
8ea2ccf110 Enhancement: support dot-notated field properties in docker labels (#2195) 2023-10-17 22:54:17 -07:00
shamoon
cbad95bf9c Fix dot status when exited (#2204) 2023-10-17 17:47:51 -07:00
shamoon
47db8be7bb Fix glances network calculation (#2201) 2023-10-17 13:31:02 -07:00
Preetham Kulai
2f4985b977 Enhancement: mjpeg stream widget placeholder image (#2192)
* added placeholder image on stream load error

* updated placeholder image to tv static animation

* Revert "updated placeholder image to tv static animation"

This reverts commit f0efdd8833.

* Inline animated tv static image

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-10-16 13:12:28 -07:00
karpaterna
8d34dc5725 Documentation: add defaultinterval option for coinmarketcap (#2191) 2023-10-15 10:09:48 -07:00
shamoon
31c33f4f32 Specify src in jsconfig 2023-10-14 12:44:37 -07:00
shamoon
ef3e98285e Fix references to podSelector in k8s manifests (#2187) 2023-10-13 19:34:19 -07:00
smoothlystable
e012ea6050 Changedetection.io: Skip checking for diff if watch never had a change (#2186)
* Only check diff in there has ever been a change

* Code style

---------

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-10-13 09:02:36 -07:00
Ado Nishimura
dcc2f3e8f3 Fix: proxmox CPU/MEM NaN when cluster has offline nodes (#2185) 2023-10-13 03:49:16 -07:00
shamoon
94718db22b Fix troubleshooting indentation 2023-10-12 13:12:11 -07:00
shamoon
c591049a1a Fix glances doc image assets 2023-10-12 11:53:15 -07:00
shamoon
fd04e93d68 Update k8s deployment with specific files (#2178) 2023-10-12 08:35:08 -07:00
patopesto
29b7d5756c Fix: possible sonarr widget queue duplicates (#2171) 2023-10-09 21:05:29 -07:00
shamoon
596e5c9b84 Fix glances fs metric for disks with colon (#2170) 2023-10-09 19:43:03 -07:00
shamoon
7ea1d0dd47 Fix calculation for docker container memory usage (#2167) 2023-10-08 10:26:20 -07:00
shamoon
4a04347518 Update README.md 2023-10-08 07:22:43 -07:00
shamoon
7bbb35db13 Update README.md 2023-10-08 06:46:20 -07:00
shamoon
d1d81e5753 Fix: emby / jellyfin isVideoDirect (#2156) 2023-10-07 20:58:05 -07:00
shamoon
4c2ecb9b0e Add hdhomerun 2023-10-06 21:01:37 -07:00
Ben Phelps
1066d17f70 Update translations.md (#2142)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-10-06 13:16:20 +00:00
shamoon
462a8e001f Change weblate links to crowdin 2023-10-06 00:04:51 -07:00
Ben Phelps
0eab49a449 New translations common.json (Yue) (#2132) 2023-10-05 23:56:05 +00:00
shamoon
24121cd5f0 run ci on merge_group 2023-10-05 15:17:05 -07:00
Lavender Shannon
8aeded4774 Update gluetun.md (#2137)
Fixed link to control server documentation
2023-10-05 22:14:37 +00:00
Denis Papec
40522fbb96 Fix: Quicklaunch shows also services without a url (#2136)
* Fix: Quicklaunch show only services with a link

Signed-off-by: Denis Papec <denis.papec@gmail.com>

* Revert "Fix: Quicklaunch show only services with a link"

This reverts commit 30ee825611.

* Filter only bookmarks and services with href

---------

Signed-off-by: Denis Papec <denis.papec@gmail.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2023-10-05 22:14:25 +00:00
Ben Phelps
76cbb6e2ed Revert "New Crowdin updates (#2124)" (#2131)
This reverts commit b29c0f809c.
2023-10-05 10:02:01 -07:00
Ben Phelps
b29c0f809c New Crowdin updates (#2124) 2023-10-05 09:49:10 -07:00
shamoon
4f41be512c Include tailwind bg-black/white, greedy ping regex, adjust position 2023-10-05 09:28:43 -07:00
shamoon
b765330b4a Fix: dot visibility in some cases, translation strings (#2129) 2023-10-05 07:19:20 -07:00
Ben Phelps
ed3055ae1b Update Crowdin configuration file 2023-10-05 11:19:02 +03:00
Ben Phelps
5460f89cc9 Update Crowdin configuration file 2023-10-05 11:07:44 +03:00
Ben Phelps
29018873f5 Update Crowdin configuration file 2023-10-05 10:37:26 +03:00
Anonymous
11cacfb823 Translated using Weblate (Basque)
Currently translated at 6.2% (34 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eu/
2023-10-05 09:29:21 +02:00
Anonymous
eddec4adc2 Translated using Weblate (Indonesian)
Currently translated at 4.4% (24 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/id/
2023-10-05 09:29:21 +02:00
Anonymous
2faf51b4c0 Translated using Weblate (Slovenian)
Currently translated at 95.9% (521 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sl/
2023-10-05 09:29:21 +02:00
Anonymous
891c387062 Translated using Weblate (Greek)
Currently translated at 33.3% (181 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/el/
2023-10-05 09:29:21 +02:00
Anonymous
3b2b6cc064 Translated using Weblate (Korean)
Currently translated at 31.8% (173 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ko/
2023-10-05 09:29:20 +02:00
Anonymous
83a5d1b17a Translated using Weblate (Slovak)
Currently translated at 23.7% (129 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sk/
2023-10-05 09:29:20 +02:00
Anonymous
29b0240abd Translated using Weblate (Thai)
Currently translated at 8.8% (48 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/th/
2023-10-05 09:29:20 +02:00
Anonymous
8ad1f9f422 Translated using Weblate (Latvian)
Currently translated at 21.7% (118 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/lv/
2023-10-05 09:29:20 +02:00
Anonymous
ea15a1b9e5 Translated using Weblate (Japanese)
Currently translated at 93.1% (506 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ja/
2023-10-05 09:29:20 +02:00
Anonymous
691ed78e75 Translated using Weblate (Ukrainian)
Currently translated at 93.1% (506 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/uk/
2023-10-05 09:29:20 +02:00
Anonymous
5f58cb285d Translated using Weblate (Esperanto)
Currently translated at 26.7% (145 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/eo/
2023-10-05 09:29:20 +02:00
Anonymous
a6696700b7 Translated using Weblate (Hindi)
Currently translated at 1.8% (10 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hi/
2023-10-05 09:29:19 +02:00
Anonymous
985ca4ae84 Translated using Weblate (Malay)
Currently translated at 46.4% (252 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ms/
2023-10-05 09:29:19 +02:00
Anonymous
ebda0f7b70 Translated using Weblate (Danish)
Currently translated at 95.9% (521 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/da/
2023-10-05 09:29:19 +02:00
Anonymous
8e7723b51d Translated using Weblate (Czech)
Currently translated at 81.7% (444 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/cs/
2023-10-05 09:29:19 +02:00
Anonymous
24635268a0 Translated using Weblate (Arabic)
Currently translated at 48.2% (262 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ar/
2023-10-05 09:29:19 +02:00
Anonymous
729c161271 Translated using Weblate (Serbian)
Currently translated at 1.8% (10 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sr/
2023-10-05 09:29:19 +02:00
Anonymous
69af86eebe Translated using Weblate (Turkish)
Currently translated at 72.3% (393 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/tr/
2023-10-05 09:29:18 +02:00
Anonymous
369a996f1f Translated using Weblate (Bulgarian)
Currently translated at 14.9% (81 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/bg/
2023-10-05 09:29:18 +02:00
Anonymous
b7b63abee0 Translated using Weblate (Telugu)
Currently translated at 39.7% (216 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/te/
2023-10-05 09:29:18 +02:00
Anonymous
4ba47c426a Translated using Weblate (Finnish)
Currently translated at 32.5% (177 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fi/
2023-10-05 09:29:17 +02:00
Anonymous
29d54b032c Translated using Weblate (Yue (Traditional))
Currently translated at 21.7% (118 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/yue_Hant/
2023-10-05 09:29:17 +02:00
Anonymous
8791aa8d0d Translated using Weblate (Portuguese (Brazil))
Currently translated at 84.8% (461 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt_BR/
2023-10-05 09:29:17 +02:00
Anonymous
337ada148c Translated using Weblate (Romanian)
Currently translated at 28.7% (156 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ro/
2023-10-05 09:29:17 +02:00
Anonymous
2c8348f5b5 Translated using Weblate (Hebrew)
Currently translated at 18.6% (101 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/he/
2023-10-05 09:29:17 +02:00
Anonymous
0eeaa99fe3 Translated using Weblate (Hungarian)
Currently translated at 86.7% (471 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hu/
2023-10-05 09:29:16 +02:00
Anonymous
38d2cc7bd7 Translated using Weblate (Croatian)
Currently translated at 86.5% (470 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/hr/
2023-10-05 09:29:16 +02:00
Anonymous
759dc9f3d2 Translated using Weblate (Swedish)
Currently translated at 24.3% (132 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/sv/
2023-10-05 09:29:16 +02:00
Anonymous
72d9a614fd Translated using Weblate (Polish)
Currently translated at 68.8% (374 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pl/
2023-10-05 09:29:16 +02:00
Anonymous
3d209bf572 Translated using Weblate (Catalan)
Currently translated at 48.0% (261 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ca/
2023-10-05 09:29:16 +02:00
Anonymous
3268db1298 Translated using Weblate (Chinese (Traditional))
Currently translated at 98.3% (534 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hant/
2023-10-05 09:29:16 +02:00
Anonymous
ab4a28d04a Translated using Weblate (Dutch)
Currently translated at 98.3% (534 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nl/
2023-10-05 09:29:15 +02:00
Anonymous
3c1644e18f Translated using Weblate (Vietnamese)
Currently translated at 8.2% (45 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/vi/
2023-10-05 09:29:15 +02:00
Anonymous
e1f6ddaeab Translated using Weblate (Norwegian Bokmål)
Currently translated at 14.9% (81 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/nb_NO/
2023-10-05 09:29:15 +02:00
Anonymous
826bad8ff4 Translated using Weblate (Italian)
Currently translated at 99.4% (540 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/it/
2023-10-05 09:29:15 +02:00
Anonymous
8aa2bbcdd3 Translated using Weblate (Chinese (Simplified))
Currently translated at 82.8% (450 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/zh_Hans/
2023-10-05 09:29:15 +02:00
Anonymous
aece2954df Translated using Weblate (Russian)
Currently translated at 79.1% (430 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/ru/
2023-10-05 09:29:15 +02:00
Anonymous
5fbdbce79c Translated using Weblate (Portuguese)
Currently translated at 76.4% (415 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/pt/
2023-10-05 09:29:14 +02:00
Anonymous
ce2bfd9d21 Translated using Weblate (French)
Currently translated at 99.6% (541 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/fr/
2023-10-05 09:29:14 +02:00
Anonymous
df4cc6086c Translated using Weblate (Spanish)
Currently translated at 99.6% (541 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/es/
2023-10-05 09:29:14 +02:00
Anonymous
2c632e2b3e Translated using Weblate (German)
Currently translated at 99.0% (538 of 543 strings)

Translation: Homepage/Homepage
Translate-URL: https://hosted.weblate.org/projects/homepage/homepage/de/
2023-10-05 09:29:14 +02:00
shamoon
6de20f0ab6 Update homepage-move.md 2023-10-05 00:26:41 -07:00
shamoon
7434d597c9 Update migration docs 2023-10-05 00:22:51 -07:00
442 changed files with 9339 additions and 7493 deletions

View File

@@ -27,5 +27,5 @@ What type of change does your PR introduce to Homepage?
- [ ] If adding a service widget or a change that requires it, I have added corresponding documentation changes. - [ ] If adding a service widget or a change that requires it, I have added corresponding documentation changes.
- [ ] If adding a new widget I have reviewed the [guidelines](https://gethomepage.dev/latest/more/development/#service-widget-guidelines). - [ ] If adding a new widget I have reviewed the [guidelines](https://gethomepage.dev/latest/more/development/#service-widget-guidelines).
- [ ] If applicable, I have checked that all tests pass with e.g. `pnpm lint`. - [ ] I have checked that all code style checks pass using pre-commit hooks and linting checks with `pnpm lint` (see development guidelines).
- [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers. - [ ] If applicable, I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.

View File

@@ -20,6 +20,7 @@ on:
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
- 'mkdocs.yml' - 'mkdocs.yml'
merge_group:
env: env:
# Use docker.io for Docker Hub if empty # Use docker.io for Docker Hub if empty
@@ -29,10 +30,28 @@ env:
jobs: jobs:
pre-commit:
name: Linting Checks
runs-on: ubuntu-22.04
steps:
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Install python
uses: actions/setup-python@v4
with:
python-version: 3.x
-
name: Check files
uses: pre-commit/action@v3.0.0
build: build:
name: Docker Build & Push name: Docker Build & Push
if: github.repository == 'gethomepage/homepage' if: github.repository == 'gethomepage/homepage'
runs-on: self-hosted runs-on: self-hosted
needs:
- pre-commit
permissions: permissions:
contents: read contents: read
packages: write packages: write

View File

@@ -11,16 +11,35 @@ on:
paths: paths:
- 'docs/**' - 'docs/**'
- 'mkdocs.yml' - 'mkdocs.yml'
merge_group:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: write
jobs: jobs:
pre-commit:
name: Linting Checks
runs-on: ubuntu-22.04
steps:
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Install python
uses: actions/setup-python@v4
with:
python-version: 3.x
-
name: Check files
uses: pre-commit/action@v3.0.0
test: test:
name: Test Build name: Test Build
if: github.repository == 'gethomepage/homepage' && github.event_name == 'pull_request' if: github.repository == 'gethomepage/homepage' && github.event_name == 'pull_request'
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- pre-commit
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
@@ -42,6 +61,8 @@ jobs:
name: Build & Deploy name: Build & Deploy
if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request' if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request'
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- pre-commit
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

19
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,19 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
exclude: "(^mkdocs\\.yml$)"
- id: check-added-large-files
- repo: https://github.com/pre-commit/mirrors-prettier
rev: 'v3.0.3'
hooks:
- id: prettier
types_or:
- javascript
- markdown
- jsx

1
.prettierrc Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our Examples of behavior that contributes to a positive environment for our
community include: community include:
* Demonstrating empathy and kindness toward other people - Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences - Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback - Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, - Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience and learning from the experience
* Focusing on what is best not just for us as individuals, but for the - Focusing on what is best not just for us as individuals, but for the
overall community overall community
Examples of unacceptable behavior include: Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or - The use of sexualized language or imagery, and sexual attention or
advances of any kind advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks - Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment - Public or private harassment
* Publishing others' private information, such as a physical or email - Publishing others' private information, such as a physical or email
address, without their explicit permission address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a - Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
## Enforcement Responsibilities ## Enforcement Responsibilities

View File

@@ -1,4 +1,5 @@
# Contributing to Homepage # Contributing to Homepage
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug - Reporting a bug
@@ -8,15 +9,19 @@ We love your input! We want to make contributing to this project as easy and tra
- Becoming a maintainer - Becoming a maintainer
## We Develop with Github ## We Develop with Github
We use github to host code, to track issues and feature requests, as well as accept pull requests. We use github to host code, to track issues and feature requests, as well as accept pull requests.
## Any contributions you make will be under the GNU General Public License v3.0 ## Any contributions you make will be under the GNU General Public License v3.0
In short, when you submit code changes, your submissions are understood to be under the same [GNU General Public License v3.0](https://choosealicense.com/licenses/gpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern. In short, when you submit code changes, your submissions are understood to be under the same [GNU General Public License v3.0](https://choosealicense.com/licenses/gpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern.
## Report bugs using Github's [issues](https://github.com/gethomepage/homepage/issues) ## Report bugs using Github's [issues](https://github.com/gethomepage/homepage/issues)
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/gethomepage/homepage/issues/new); it's that easy! We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/gethomepage/homepage/issues/new); it's that easy!
## Write bug reports with detail, background, and sample configurations ## Write bug reports with detail, background, and sample configurations
Homepage includes a lot of configuration options and is often deploying in larger systems. Please include as much information (configurations, deployment method, Docker & API versions, etc) as you can when reporting an issue. Homepage includes a lot of configuration options and is often deploying in larger systems. Please include as much information (configurations, deployment method, Docker & API versions, etc) as you can when reporting an issue.
**Great Bug Reports** tend to have: **Great Bug Reports** tend to have:
@@ -29,16 +34,20 @@ Homepage includes a lot of configuration options and is often deploying in large
- What actually happens - What actually happens
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
People *love* thorough bug reports. I'm not even kidding. People _love_ thorough bug reports. I'm not even kidding.
## Development Guidelines ## Development Guidelines
Please see the [documentation regarding development](https://gethomepage.dev/latest/more/development/) and specifically the [guidelines for new service widgets](https://gethomepage.dev/latest/more/development/#service-widget-guidelines) if you are considering making one. Please see the [documentation regarding development](https://gethomepage.dev/latest/more/development/) and specifically the [guidelines for new service widgets](https://gethomepage.dev/latest/more/development/#service-widget-guidelines) if you are considering making one.
## Use a Consistent Coding Style ## Use a Consistent Coding Style
This project follows the [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript), please follow it when submitting pull requests.
Please see information in the docs regarding [code formatting with pre-commit hooks](https://gethomepage.dev/latest/more/development.md#code-formatting-with-pre-commit-hooks).
## License ## License
By contributing, you agree that your contributions will be licensed under its GNU General Public License. By contributing, you agree that your contributions will be licensed under its GNU General Public License.
## References ## References
This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/main/CONTRIBUTING.md) This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/main/CONTRIBUTING.md)

View File

@@ -16,10 +16,12 @@
<p align="center"> <p align="center">
<a href="https://github.com/gethomepage/homepage/actions/workflows/docker-publish.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/gethomepage/homepage/docker-publish.yml"></a> <a href="https://github.com/gethomepage/homepage/actions/workflows/docker-publish.yml"><img alt="GitHub Workflow Status (with event)" src="https://img.shields.io/github/actions/workflow/status/gethomepage/homepage/docker-publish.yml"></a>
&nbsp; &nbsp;
<a href="https://hosted.weblate.org/engage/homepage/"><img src="https://hosted.weblate.org/widgets/homepage/-/homepage/svg-badge.svg" alt="Weblate"></a> <a href="https://crowdin.com/project/gethomepage" target="_blank"><img src="https://badges.crowdin.net/gethomepage/localized.svg"></a>
&nbsp; &nbsp;
<a href="https://discord.gg/k4ruYNrudu"><img alt="Discord" src="https://img.shields.io/discord/1019316731635834932"></a> <a href="https://discord.gg/k4ruYNrudu"><img alt="Discord" src="https://img.shields.io/discord/1019316731635834932"></a>
&nbsp; &nbsp;
<a href="http://gethomepage.dev/latest/" title="Docs"><img title="Docs" src="https://github.com/gethomepage/homepage/actions/workflows/docs-publish.yml/badge.svg"/></a>
&nbsp;
<a href="https://paypal.me/phelpsben" title="Donate"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/benphelps"></a> <a href="https://paypal.me/phelpsben" title="Donate"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/benphelps"></a>
</p> </p>
@@ -122,7 +124,7 @@ pnpm dev
# Configuration # Configuration
Please refere to the [homepage documentation](https://gethomepage.dev/) website for more information. Everything you need to know about configuring Homepage is there. Please read everything carefully before asking for help, as most questions are answered there or are simple YAML configuration issues. Please refer to the [homepage documentation](https://gethomepage.dev/) website for more information. Everything you need to know about configuring Homepage is there. Please read everything carefully before asking for help, as most questions are answered there or are simple YAML configuration issues.
# Development # Development
@@ -144,6 +146,8 @@ This is a [Next.js](https://nextjs.org/) application, see their documentation fo
# Documentation # Documentation
The homepage documentation is available at [https://gethomepage.dev/](https://gethomepage.dev/).
Homepage uses Material for MkDocs for documentation. To run the documentation locally, first install the dependencies: Homepage uses Material for MkDocs for documentation. To run the documentation locally, first install the dependencies:
```bash ```bash

3
crowdin.yml Normal file
View File

@@ -0,0 +1,3 @@
files:
- source: /public/locales/en/*.json
translation: /public/locales/%osx_locale%/%original_file_name%

View File

@@ -153,6 +153,23 @@ labels:
- homepage.widget.fields=["field1","field2"] # optional - homepage.widget.fields=["field1","field2"] # optional
``` ```
You can add specify fields for e.g. the [CustomAPI](/widgets/services/customapi) widget by using array-style dot notation:
```yaml
labels:
- homepage.group=Media
- homepage.name=Emby
- homepage.icon=emby.png
- homepage.href=http://emby.home/
- homepage.description=Media server
- homepage.widget.type=customapi
- homepage.widget.url=http://argus.service/api/v1/service/summary/emby
- homepage.widget.field[0].label=Deployed Version
- homepage.widget.field[0].field.status=deployed_version
- homepage.widget.field[1].label=Latest Version
- homepage.widget.field[1].field.status=latest_version
```
## Docker Swarm ## Docker Swarm
Docker swarm is supported and Docker services are specified with the same `server` and `container` notation. To enable swarm support you will need to include a `swarm` setting in your docker.yaml, e.g. Docker swarm is supported and Docker services are specified with the same `server` and `container` notation. To enable swarm support you will need to include a `swarm` setting in your docker.yaml, e.g.

View File

@@ -36,7 +36,7 @@ Inside of the service you'd like to connect to a pod:
The `app` field is used to create a label selector, in this example case it would match pods with the label: `app.kubernetes.io/name=emby`. The `app` field is used to create a label selector, in this example case it would match pods with the label: `app.kubernetes.io/name=emby`.
Sometimes this is insufficient for complex or atypical application deployments. In these cases, the `podSelector` field can be used. Any field selector can be used with it, so it allows for some very powerful selection capabilities. Sometimes this is insufficient for complex or atypical application deployments. In these cases, the `pod-selector` field can be used. Any field selector can be used with it, so it allows for some very powerful selection capabilities.
For instance, it can be utilized to roll multiple underlying deployments under one application to see a high-level aggregate: For instance, it can be utilized to roll multiple underlying deployments under one application to see a high-level aggregate:
@@ -47,7 +47,7 @@ For instance, it can be utilized to roll multiple underlying deployments under o
description: Matrix Synapse Powered Chat description: Matrix Synapse Powered Chat
app: matrix-element app: matrix-element
namespace: comms namespace: comms
podSelector: >- pod-selector: >-
app.kubernetes.io/instance in ( app.kubernetes.io/instance in (
matrix-element, matrix-element,
matrix-media-repo, matrix-media-repo,
@@ -58,7 +58,7 @@ For instance, it can be utilized to roll multiple underlying deployments under o
!!! note !!! note
A blank string as a podSelector does not deactivate it, but will actually select all pods in the namespace. This is a useful way to capture the resource usage of a complex application siloed to a single namespace, like Longhorn. A blank string as a pod-selector does not deactivate it, but will actually select all pods in the namespace. This is a useful way to capture the resource usage of a complex application siloed to a single namespace, like Longhorn.
## Automatic Service Discovery ## Automatic Service Discovery
@@ -77,7 +77,7 @@ metadata:
gethomepage.dev/name: Emby gethomepage.dev/name: Emby
gethomepage.dev/widget.type: "emby" gethomepage.dev/widget.type: "emby"
gethomepage.dev/widget.url: "https://emby.example.com" gethomepage.dev/widget.url: "https://emby.example.com"
gethomepage.dev/podSelector: "" gethomepage.dev/pod-selector: ""
gethomepage.dev/weight: 10 # optional gethomepage.dev/weight: 10 # optional
spec: spec:
rules: rules:
@@ -110,10 +110,11 @@ metadata:
gethomepage.dev/description: Media Server gethomepage.dev/description: Media Server
gethomepage.dev/group: Media gethomepage.dev/group: Media
gethomepage.dev/icon: emby.png gethomepage.dev/icon: emby.png
gethomepage.dev/app: emby-app # optional, may be needed if app.kubernetes.io/name != ingress metadata.name
gethomepage.dev/name: Emby gethomepage.dev/name: Emby
gethomepage.dev/widget.type: "emby" gethomepage.dev/widget.type: "emby"
gethomepage.dev/widget.url: "https://emby.example.com" gethomepage.dev/widget.url: "https://emby.example.com"
gethomepage.dev/podSelector: "" gethomepage.dev/pod-selector: ""
gethomepage.dev/weight: 10 # optional gethomepage.dev/weight: 10 # optional
spec: spec:
entryPoints: entryPoints:

View File

@@ -391,7 +391,7 @@ You can choose from the following styles for docker or k8s status and ping: `dot
For example: For example:
```yaml ```yaml
statusStyle: 'dot' statusStyle: "dot"
``` ```
or per-service (`services.yaml`) with: or per-service (`services.yaml`) with:

View File

@@ -298,10 +298,32 @@ spec:
containerPort: 3000 containerPort: 3000
protocol: TCP protocol: TCP
volumeMounts: volumeMounts:
- name: homepage-config - mountPath: /app/config/custom.js
mountPath: /app/config name: homepage-config
- name: logs subPath: custom.js
mountPath: /app/config/logs - mountPath: /app/config/custom.css
name: homepage-config
subPath: custom.css
- mountPath: /app/config/bookmarks.yaml
name: homepage-config
subPath: bookmarks.yaml
- mountPath: /app/config/docker.yaml
name: homepage-config
subPath: docker.yaml
- mountPath: /app/config/kubernetes.yaml
name: homepage-config
subPath: kubernetes.yaml
- mountPath: /app/config/services.yaml
name: homepage-config
subPath: services.yaml
- mountPath: /app/config/settings.yaml
name: homepage-config
subPath: settings.yaml
- mountPath: /app/config/widgets.yaml
name: homepage-config
subPath: widgets.yaml
- mountPath: /app/config/logs
name: logs
volumes: volumes:
- name: homepage-config - name: homepage-config
configMap: configMap:

View File

@@ -31,6 +31,15 @@ Once dependencies have been installed you can lint your code with
pnpm lint pnpm lint
``` ```
## Code formatting with pre-commit hooks
To ensure a consistent style and formatting across the project source, the project utilizes Git [`pre-commit`](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) hooks to perform some formatting and linting before a commit is allowed.
That way, everyone uses the same style and some common issues can be caught early on.
Once installed, hooks will run when you commit. If the formatting isn't quite right or a linter catches something, the commit will be rejected.
You'll need to look at the output and fix the issue. Some hooks will format failing files, so all you need to do is `git add` those files again
and retry your commit.
## Service Widget Guidelines ## Service Widget Guidelines
To ensure cohesiveness of various widgets, the following should be used as a guide for developing new widgets: To ensure cohesiveness of various widgets, the following should be used as a guide for developing new widgets:

View File

@@ -3,6 +3,6 @@ title: Homepage Move
description: Homepage Container Deprecation description: Homepage Container Deprecation
--- ---
As of v0.7.1 homepage migrated from benphelps/homepage to an "orgnization" located at gethomepage/homepage. The reason for this is to setup the project for longevity and allow for community maintenance. As of v0.7.2 homepage migrated from benphelps/homepage to an "organization" repository located at [gethomepage/homepage](https://github.com/gethomepage/homepage/). The reason for this was to setup the project for longevity and allow for community maintenance.
Migrating your installation should be as simple as changing `image: ghcr.io/benphelps/homepage:latest` to `image: ghcr.io/gethomepage/homepage:latest`. Migrating your installation should be as simple as changing `image: ghcr.io/benphelps/homepage:latest` to `image: ghcr.io/gethomepage/homepage:latest`.

View File

@@ -3,12 +3,17 @@ title: Translations
description: Contributing Translations description: Contributing Translations
--- ---
Homepage is developed in English, most other supported languages are provided via Google Translate. When a i18n key is not found, the fallback language is English. Homepage is developed in English, component contributions must be in English. All translations are community provided, so a huge thanks go out to all those who have helped out so far!
## Support Translations ## Support Translations
If you'd like to lend a hand in translating Homepage into more languages, or to improve existing translations, the process is very simple. If you'd like to lend a hand in translating Homepage into more languages, or to improve existing translations, the process is very simple:
Everything can be done from a simple to use web interface here: https://hosted.weblate.org/projects/homepage/homepage/ 1. Create a free account at [Crowdin](https://crowdin.com/join)
2. Visit the [Homepage project](https://crowdin.com/project/gethomepage)
3. Select the language you'd like to translate
4. Start translating!
When creating a new language, it can take 5 to 10 minutes before you'll see translatable strings added, but the process _is_ automatic. Once the strings are added, you can then start translating them. ## Adding a new language
If you'd like to add a new language, please [create a new Discussion on Crowdin](https://crowdin.com/project/gethomepage/discussions), and we'll add it to the project.

View File

@@ -29,7 +29,9 @@ All service widgets work essentially the same, that is, homepage makes a proxied
3. If you have verified that homepage can in fact reach the service then you can also check the API output using e.g. `curl`, which is often helpful if you do need to file a bug report. Again, depending on your networking setup this may need to be run from _inside the container_ as IP / hostname resolution can differ inside vs outside. 3. If you have verified that homepage can in fact reach the service then you can also check the API output using e.g. `curl`, which is often helpful if you do need to file a bug report. Again, depending on your networking setup this may need to be run from _inside the container_ as IP / hostname resolution can differ inside vs outside.
_Note: `curl` is not installed in the base image by default but can be added inside the container with `apk add curl`._ !!! note
`curl` is not installed in the base image by default but can be added inside the container with `apk add curl`.
The exact API endpoints and authentication vary of course, but in many cases instructions can be found by searching the web or if you feel comfortable looking at the homepage source code (e.g. `src/widgets/{widget}/widget.js`). The exact API endpoints and authentication vary of course, but in many cases instructions can be found by searching the web or if you feel comfortable looking at the homepage source code (e.g. `src/widgets/{widget}/widget.js`).

View File

@@ -13,6 +13,7 @@ widget:
currency: GBP # Optional currency: GBP # Optional
symbols: [BTC, LTC, ETH] symbols: [BTC, LTC, ETH]
key: apikeyapikeyapikeyapikeyapikey key: apikeyapikeyapikeyapikeyapikey
defaultinterval: 7d # Optional
``` ```
You can also specify slugs instead of symbols (since symbols aren't garaunteed to be unique). If you supply both, slugs will be used. For example: You can also specify slugs instead of symbols (since symbols aren't garaunteed to be unique). If you supply both, slugs will be used. For example:

View File

@@ -3,7 +3,7 @@ title: Glances
description: Glances Widget Configuration description: Glances Widget Configuration
--- ---
<img width="1614" alt="glances" src="https://github.com/gethomepage/homepage-docs/assets/82196/25648c97-2c1b-4db0-b5a5-f1509806079c"> <img width="1614" alt="glances" src="https://github-production-user-asset-6210df.s3.amazonaws.com/82196/257382012-25648c97-2c1b-4db0-b5a5-f1509806079c.png">
_(Find the Glances information widget [here](../info/glances.md))_ _(Find the Glances information widget [here](../info/glances.md))_
@@ -59,7 +59,7 @@ The metric field in the configuration determines the type of system monitoring d
All widgets offer an alternative to the full or "graph" view, which is the compact, or "graphless" view. All widgets offer an alternative to the full or "graph" view, which is the compact, or "graphless" view.
<img width="970" alt="Screenshot 2023-09-06 at 1 51 48PM" src="https://github.com/gethomepage/homepage-docs/assets/82196/cc6b9adc-4218-4274-96ca-36c3e64de5d0"> <img width="970" alt="Screenshot 2023-09-06 at 1 51 48PM" src="https://github-production-user-asset-6210df.s3.amazonaws.com/82196/265985295-cc6b9adc-4218-4274-96ca-36c3e64de5d0.png">
To switch to the alternative "graphless" view, simply passs `chart: false` as an option to the widget, like so: To switch to the alternative "graphless" view, simply passs `chart: false` as an option to the widget, like so:

View File

@@ -3,7 +3,7 @@ title: Gluetun
description: Gluetun Widget Configuration description: Gluetun Widget Configuration
--- ---
Requires [HTTP control server options](https://github.com/qdm12/gluetun/wiki/HTTP-control-server-options) to be enabled. Requires [HTTP control server options](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md) to be enabled.
Allowed fields: `["public_ip", "region", "country"]`. Allowed fields: `["public_ip", "region", "country"]`.

View File

@@ -0,0 +1,12 @@
---
title: HDHomerun
description: HDHomerun Widget Configuration
---
Allowed fields: `["channels", "hd"]`.
```yaml
widget:
type: hdhomerun
url: http://hdhomerun.host.or.ip
```

View File

@@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": "./src/", "baseUrl": "./src/",
} },
"include": ["src/**/*"]
} }

1
k3d/.gitignore vendored
View File

@@ -1,2 +1 @@
kubeconfig kubeconfig

View File

@@ -11,7 +11,7 @@ All the commands in the document should be run from the `k3d` directory.
## Requisite Tools ## Requisite Tools
| Tool | Description | | Tool | Description |
|-------------------------------------------------------------|----------------------------------------------------------| | ----------------------------------------------------------- | -------------------------------------------------------- |
| [docker](https://docker.io) | Docker container runtime | | [docker](https://docker.io) | Docker container runtime |
| [kubectl](https://kubernetes.io/releases/download/#kubectl) | Kubernetes CLI | | [kubectl](https://kubernetes.io/releases/download/#kubectl) | Kubernetes CLI |
| [helm](https://helm.sh) | Kubernetes package manager | | [helm](https://helm.sh) | Kubernetes package manager |
@@ -20,7 +20,6 @@ All the commands in the document should be run from the `k3d` directory.
| [tilt](https://tilt.dev) | (Optional) Local CI loop for kubernetes deployment | | [tilt](https://tilt.dev) | (Optional) Local CI loop for kubernetes deployment |
| [direnv](https://direnv.net/) | (Optional) Automatically loads `kubeconfig` via `.envrc` | | [direnv](https://direnv.net/) | (Optional) Automatically loads `kubeconfig` via `.envrc` |
## One-off Test Deployments ## One-off Test Deployments
Create a cluster: Create a cluster:
@@ -57,7 +56,7 @@ tilt up
Press space bar to open the tilt web UI, which is quite informative. Press space bar to open the tilt web UI, which is quite informative.
Open the Homepage deployment: Finally, open the Homepage deployment:
```sh ```sh
xdg-open http://homepage.k3d.localhost:8080/ xdg-open http://homepage.k3d.localhost:8080/

View File

@@ -2,9 +2,9 @@
## Requirements ## Requirements
* Kubernetes 1.19+ - Kubernetes 1.19+
* Metrics service - Metrics service
* An Ingress controller - An Ingress controller
## Deployment ## Deployment
@@ -98,7 +98,7 @@ be configured on the service entry.
This works by creating a label selector `app.kubernetes.io/name=home-assistant`, This works by creating a label selector `app.kubernetes.io/name=home-assistant`,
which typically will be the same both for the ingress and the deployment. However, which typically will be the same both for the ingress and the deployment. However,
some deployments can be complex and will not conform to this rule. In such some deployments can be complex and will not conform to this rule. In such
cases the `podSelector` variable can bridge the gap. Any field selector can cases the `pod-selector` variable can bridge the gap. Any field selector can
be used in it which allows for some powerful selection capabilities. be used in it which allows for some powerful selection capabilities.
For instance, it can be utilized to roll multiple underlying deployments under For instance, it can be utilized to roll multiple underlying deployments under
@@ -112,7 +112,7 @@ one application to see a high-level aggregate:
description: Matrix Synapse Powered Chat description: Matrix Synapse Powered Chat
app: matrix-element app: matrix-element
namespace: comms namespace: comms
podSelector: >- pod-selector: >-
app.kubernetes.io/instance in ( app.kubernetes.io/instance in (
matrix-element, matrix-element,
matrix-media-repo, matrix-media-repo,

View File

@@ -59,6 +59,7 @@ nav:
- widgets/services/gluetun.md - widgets/services/gluetun.md
- widgets/services/gotify.md - widgets/services/gotify.md
- widgets/services/grafana.md - widgets/services/grafana.md
- widgets/services/hdhomerun.md
- widgets/services/healthchecks.md - widgets/services/healthchecks.md
- widgets/services/homeassistant.md - widgets/services/homeassistant.md
- widgets/services/homebridge.md - widgets/services/homebridge.md
@@ -149,6 +150,7 @@ nav:
- more/index.md - more/index.md
- more/development.md - more/development.md
- more/translations.md - more/translations.md
- more/homepage-move.md
theme: theme:
name: material name: material

View File

@@ -69,7 +69,7 @@ function prettyBytes(number, options) {
const exponent = Math.min( const exponent = Math.min(
Math.floor(options.binary ? Math.log(number) / Math.log(1024) : Math.log10(number) / 3), Math.floor(options.binary ? Math.log(number) / Math.log(1024) : Math.log10(number) / 3),
UNITS.length - 1 UNITS.length - 1,
); );
number /= (options.binary ? 1024 : 1000) ** exponent; number /= (options.binary ? 1024 : 1000) ** exponent;
@@ -94,13 +94,18 @@ module.exports = {
{ {
init: (i18next) => { init: (i18next) => {
i18next.services.formatter.add("bytes", (value, lng, options) => i18next.services.formatter.add("bytes", (value, lng, options) =>
prettyBytes(parseFloat(value), { locale: lng, ...options }) prettyBytes(parseFloat(value), { locale: lng, ...options }),
); );
i18next.services.formatter.add("rate", (value, lng, options) => { i18next.services.formatter.add("rate", (value, lng, options) => {
const k = options.binary ? 1024 : 1000; const k = options.binary ? 1024 : 1000;
const sizes = options.bits ? (options.binary ? BIBIT_UNITS : BIT_UNITS) : (options.binary ? BIBYTE_UNITS : BYTE_UNITS); const sizes = options.bits
? options.binary
? BIBIT_UNITS
: BIT_UNITS
: options.binary
? BIBYTE_UNITS
: BYTE_UNITS;
if (value === 0) return `0 ${sizes[0]}/s`; if (value === 0) return `0 ${sizes[0]}/s`;
@@ -109,14 +114,14 @@ module.exports = {
const i = options.binary ? 2 : Math.floor(Math.log(value) / Math.log(k)); const i = options.binary ? 2 : Math.floor(Math.log(value) / Math.log(k));
const formatted = new Intl.NumberFormat(lng, { maximumFractionDigits: dm, minimumFractionDigits: dm }).format( const formatted = new Intl.NumberFormat(lng, { maximumFractionDigits: dm, minimumFractionDigits: dm }).format(
parseFloat(value / k ** i) parseFloat(value / k ** i),
); );
return `${formatted} ${sizes[i]}/s`; return `${formatted} ${sizes[i]}/s`;
}); });
i18next.services.formatter.add("percent", (value, lng, options) => i18next.services.formatter.add("percent", (value, lng, options) =>
new Intl.NumberFormat(lng, { style: "percent", ...options }).format(parseFloat(value) / 100.0) new Intl.NumberFormat(lng, { style: "percent", ...options }).format(parseFloat(value) / 100.0),
); );
}, },
type: "3rdParty", type: "3rdParty",

26
package-lock.json generated
View File

@@ -30,7 +30,6 @@
"react-i18next": "^11.18.6", "react-i18next": "^11.18.6",
"react-icons": "^4.4.0", "react-icons": "^4.4.0",
"recharts": "^2.7.2", "recharts": "^2.7.2",
"shvl": "^3.0.0",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.17.12", "systeminformation": "^5.17.12",
"tough-cookie": "^4.1.2", "tough-cookie": "^4.1.2",
@@ -44,14 +43,14 @@
"eslint": "^8.24.0", "eslint": "^8.24.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^12.3.1", "eslint-config-next": "^12.3.1",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.8", "eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.4.16", "postcss": "^8.4.16",
"prettier": "^2.7.1", "prettier": "^3.0.3",
"tailwind-scrollbar": "^2.0.1", "tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.1.8", "tailwindcss": "^3.1.8",
"typescript": "^4.8.3" "typescript": "^4.8.3"
@@ -2264,9 +2263,9 @@
} }
}, },
"node_modules/eslint-config-prettier": { "node_modules/eslint-config-prettier": {
"version": "8.8.0", "version": "9.0.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
"integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
"dev": true, "dev": true,
"bin": { "bin": {
"eslint-config-prettier": "bin/cli.js" "eslint-config-prettier": "bin/cli.js"
@@ -5008,15 +5007,15 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.8.7", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin/prettier.cjs"
}, },
"engines": { "engines": {
"node": ">=10.13.0" "node": ">=14"
}, },
"funding": { "funding": {
"url": "https://github.com/prettier/prettier?sponsor=1" "url": "https://github.com/prettier/prettier?sponsor=1"
@@ -5628,11 +5627,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/shvl": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shvl/-/shvl-3.0.0.tgz",
"integrity": "sha512-5IomAM3ykE/g9K9L6lhODc+TpCuN03rrhlboegeKyyfh66DDdpRD5JN37DYhNHH+RaYjiIDx64K/Ms/xQYOR5w=="
},
"node_modules/side-channel": { "node_modules/side-channel": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",

View File

@@ -32,7 +32,6 @@
"react-i18next": "^11.18.6", "react-i18next": "^11.18.6",
"react-icons": "^4.4.0", "react-icons": "^4.4.0",
"recharts": "^2.7.2", "recharts": "^2.7.2",
"shvl": "^3.0.0",
"swr": "^1.3.0", "swr": "^1.3.0",
"systeminformation": "^5.17.12", "systeminformation": "^5.17.12",
"tough-cookie": "^4.1.2", "tough-cookie": "^4.1.2",
@@ -46,14 +45,14 @@
"eslint": "^8.24.0", "eslint": "^8.24.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-next": "^12.3.1", "eslint-config-next": "^12.3.1",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.8", "eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.4.16", "postcss": "^8.4.16",
"prettier": "^2.7.1", "prettier": "^3.0.3",
"tailwind-scrollbar": "^2.0.1", "tailwind-scrollbar": "^2.0.1",
"tailwindcss": "^3.1.8", "tailwindcss": "^3.1.8",
"typescript": "^4.8.3" "typescript": "^4.8.3"

34
pnpm-lock.yaml generated
View File

@@ -71,9 +71,6 @@ dependencies:
recharts: recharts:
specifier: ^2.7.2 specifier: ^2.7.2
version: 2.7.2(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0) version: 2.7.2(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)
shvl:
specifier: ^3.0.0
version: 3.0.0
swr: swr:
specifier: ^1.3.0 specifier: ^1.3.0
version: 1.3.0(react@18.2.0) version: 1.3.0(react@18.2.0)
@@ -115,8 +112,8 @@ devDependencies:
specifier: ^12.3.1 specifier: ^12.3.1
version: 12.3.4(eslint@8.37.0)(typescript@4.9.5) version: 12.3.4(eslint@8.37.0)(typescript@4.9.5)
eslint-config-prettier: eslint-config-prettier:
specifier: ^8.5.0 specifier: ^9.0.0
version: 8.8.0(eslint@8.37.0) version: 9.0.0(eslint@8.37.0)
eslint-plugin-import: eslint-plugin-import:
specifier: ^2.26.0 specifier: ^2.26.0
version: 2.27.5(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.37.0) version: 2.27.5(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-typescript@2.7.1)(eslint@8.37.0)
@@ -125,7 +122,7 @@ devDependencies:
version: 6.7.1(eslint@8.37.0) version: 6.7.1(eslint@8.37.0)
eslint-plugin-prettier: eslint-plugin-prettier:
specifier: ^4.2.1 specifier: ^4.2.1
version: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.37.0)(prettier@2.8.7) version: 4.2.1(eslint-config-prettier@9.0.0)(eslint@8.37.0)(prettier@3.0.3)
eslint-plugin-react: eslint-plugin-react:
specifier: ^7.31.8 specifier: ^7.31.8
version: 7.32.2(eslint@8.37.0) version: 7.32.2(eslint@8.37.0)
@@ -136,8 +133,8 @@ devDependencies:
specifier: ^8.4.16 specifier: ^8.4.16
version: 8.4.21 version: 8.4.21
prettier: prettier:
specifier: ^2.7.1 specifier: ^3.0.3
version: 2.8.7 version: 3.0.3
tailwind-scrollbar: tailwind-scrollbar:
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.1.0(tailwindcss@3.3.0) version: 2.1.0(tailwindcss@3.3.0)
@@ -1503,8 +1500,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-config-prettier@8.8.0(eslint@8.37.0): /eslint-config-prettier@9.0.0(eslint@8.37.0):
resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
eslint: '>=7.0.0' eslint: '>=7.0.0'
@@ -1628,7 +1625,7 @@ packages:
semver: 6.3.0 semver: 6.3.0
dev: true dev: true
/eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.37.0)(prettier@2.8.7): /eslint-plugin-prettier@4.2.1(eslint-config-prettier@9.0.0)(eslint@8.37.0)(prettier@3.0.3):
resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
peerDependencies: peerDependencies:
@@ -1640,8 +1637,8 @@ packages:
optional: true optional: true
dependencies: dependencies:
eslint: 8.37.0 eslint: 8.37.0
eslint-config-prettier: 8.8.0(eslint@8.37.0) eslint-config-prettier: 9.0.0(eslint@8.37.0)
prettier: 2.8.7 prettier: 3.0.3
prettier-linter-helpers: 1.0.0 prettier-linter-helpers: 1.0.0
dev: true dev: true
@@ -3206,9 +3203,10 @@ packages:
fast-diff: 1.2.0 fast-diff: 1.2.0
dev: true dev: true
/prettier@2.8.7: /prettier@3.0.3:
resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==} resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==}
engines: {node: '>=10.13.0'} engines: {node: '>=14'}
hasBin: true
dev: true dev: true
/pretty-bytes@6.1.0: /pretty-bytes@6.1.0:
@@ -3614,10 +3612,6 @@ packages:
rechoir: 0.6.2 rechoir: 0.6.2
dev: false dev: false
/shvl@3.0.0:
resolution: {integrity: sha512-5IomAM3ykE/g9K9L6lhODc+TpCuN03rrhlboegeKyyfh66DDdpRD5JN37DYhNHH+RaYjiIDx64K/Ms/xQYOR5w==}
dev: false
/side-channel@1.0.4: /side-channel@1.0.4:
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies: dependencies:

View File

@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
} };

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "خطأ", "error": "خطأ",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "إجتاز", "passed": "إجتاز",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"ping": "Ping", "ping": "Ping",
"error": "Грешка" "error": "Грешка",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Aprobat", "passed": "Aprobat",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Chyba", "error": "Chyba",
"ping": "Odezva" "ping": "Odezva",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Úspěšné", "passed": "Úspěšné",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -136,7 +136,9 @@
}, },
"ping": { "ping": {
"error": "Σφάλμα", "error": "Σφάλμα",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Παίζει", "playing": "Παίζει",

View File

@@ -79,10 +79,12 @@
"partial": "Partial" "partial": "Partial"
}, },
"ping": { "ping": {
"http_status": "HTTP status",
"error": "Error", "error": "Error",
"ping": "Ping", "ping": "Ping",
"down": "Down", "down": "Down",
"up": "Up" "up": "Up",
"not_available": "Not Available"
}, },
"emby": { "emby": {
"playing": "Playing", "playing": "Playing",

View File

@@ -67,7 +67,9 @@
}, },
"ping": { "ping": {
"error": "Eraro", "error": "Eraro",
"ping": "Sondaĵo" "ping": "Sondaĵo",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Ludante", "playing": "Ludante",

View File

@@ -1,23 +1,42 @@
{ {
"common": {
"bytes": "{{value, bytes}}",
"bits": "{{value, bytes(bits: true)}}",
"bbytes": "{{value, bytes(binary: true)}}",
"bbits": "{{value, bytes(bits: true; binary: true)}}",
"byterate": "{{value, rate(bits: false)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bitrate": "{{value, rate(bits: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"percent": "{{value, percent}}",
"number": "{{value, number}}",
"ms": "{{value, number}}"
},
"widget": { "widget": {
"missing_type": "Falta el tipo de widget: {{type}}", "missing_type": "Tipo de Widget que falta: {{type}}",
"api_error": "Error de API", "api_error": "Error en API",
"status": "Estado",
"information": "Información", "information": "Información",
"url": "URL", "status": "Estado",
"url": "Enlace",
"raw_error": "Error sin procesar", "raw_error": "Error sin procesar",
"response_data": "Datos de respuesta" "response_data": "Datos de respuesta"
}, },
"weather": {
"current": "Ubicación actual",
"allow": "Clic para permitir",
"updating": "Actualizando",
"wait": "Espera, por favor"
},
"search": { "search": {
"placeholder": "Buscar…" "placeholder": "Buscar…"
}, },
"resources": { "resources": {
"cpu": "CPU",
"mem": "MEM",
"total": "Total", "total": "Total",
"free": "Libre", "free": "Libre",
"used": "Usado", "used": "Usado",
"load": "Carga", "load": "Carga",
"cpu": "CPU",
"mem": "MEM",
"temp": "TEMP", "temp": "TEMP",
"max": "Máx.", "max": "Máx.",
"uptime": "ARRIBA", "uptime": "ARRIBA",
@@ -26,21 +45,46 @@
"hours": "Horas", "hours": "Horas",
"minutes": "Minutos" "minutes": "Minutos"
}, },
"unifi": {
"users": "Usuarios",
"uptime": "Tiempo de actividad",
"days": "Días",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Dispositivos",
"lan_devices": "Dispositivos LAN",
"wlan_devices": "Dispositivos WLAN",
"lan_users": "Usuarios LAN",
"wlan_users": "Usuarios WLAN",
"up": "ARRIBA",
"down": "CAÍDO",
"wait": "Espera, por favor",
"empty_data": "Se desconoce el estado del subsistema"
},
"docker": { "docker": {
"rx": "Recibido", "rx": "Recibido",
"tx": "Transmitido", "tx": "Transmitido",
"mem": "Memoria", "mem": "MEM",
"cpu": "Procesador", "cpu": "CPU",
"running": "Ejecutando",
"offline": "Desconectado", "offline": "Desconectado",
"error": "Fallo", "error": "Fallo",
"unknown": "Desconocido", "unknown": "Desconocido",
"running": "Ejecutando", "healthy": "Saludable",
"starting": "Comenzando", "starting": "Comenzando",
"unhealthy": "Insalubre", "unhealthy": "Insalubre",
"not_found": "No encontrado", "not_found": "No encontrado",
"exited": "Salida", "exited": "Salida",
"partial": "Parcial", "partial": "Parcial"
"healthy": "Saludable" },
"ping": {
"http_status": "Estado HTTP",
"error": "Fallo",
"ping": "Ping",
"down": "Abajo",
"up": "Arriba",
"not_available": "No Disponible"
}, },
"emby": { "emby": {
"playing": "Reproduciendo", "playing": "Reproduciendo",
@@ -48,10 +92,43 @@
"bitrate": "Tasa de bits", "bitrate": "Tasa de bits",
"no_active": "Sin transmisiones activas", "no_active": "Sin transmisiones activas",
"movies": "Películas", "movies": "Películas",
"series": "Series", "series": "Serie",
"episodes": "Episodios", "episodes": "Episodios",
"songs": "Canciones" "songs": "Canciones"
}, },
"evcc": {
"pv_power": "Producción",
"battery_soc": "Batería",
"grid_power": "Red",
"home_power": "Consumo",
"charge_power": "Cargador",
"watt_hour": "vatio-hora (Wh)"
},
"flood": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
"freshrss": {
"subscriptions": "Suscripciones",
"unread": "Sin leer"
},
"caddy": {
"upstreams": "Upstream (desarrollo de software)",
"requests": "Peticiones actuales",
"requests_failed": "Peticiones fallidas"
},
"changedetectionio": {
"totalObserved": "Total Observados",
"diffsDetected": "Diferencias detectadas"
},
"channelsdvrserver": {
"shows": "Espectáculos",
"recordings": "Grabaciones",
"scheduled": "Programado",
"passes": "Pases"
},
"tautulli": { "tautulli": {
"playing": "Reproduciendo", "playing": "Reproduciendo",
"transcoding": "Transcodificando", "transcoding": "Transcodificando",
@@ -59,31 +136,95 @@
"no_active": "Sin transmisiones activas", "no_active": "Sin transmisiones activas",
"plex_connection_error": "Comprueba la conexión a Plex" "plex_connection_error": "Comprueba la conexión a Plex"
}, },
"omada": {
"connectedAp": "AP conectados",
"activeUser": "Dispositivos activos",
"alerts": "Alertas",
"connectedGateway": "Pasarelas conectadas",
"connectedSwitches": "Interruptores conectados"
},
"nzbget": {
"rate": "Tasa",
"remaining": "Restante",
"downloaded": "Descargado"
},
"plex": {
"streams": "Transmisiones activas",
"albums": "Álbumes",
"movies": "Películas",
"tv": "Series"
},
"sabnzbd": {
"rate": "Tasa",
"queue": "En cola",
"timeleft": "Tiempo restante"
},
"rutorrent": { "rutorrent": {
"active": "Activo", "active": "Activo",
"upload": "Subida", "upload": "Subida",
"download": "Bajada" "download": "Descarga"
},
"transmission": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
"qbittorrent": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
"qnap": {
"cpuUsage": "Uso de la Cpu",
"memUsage": "Uso de la memoria",
"systemTempC": "Temperatura del sistema",
"poolUsage": "Comprobación del uso del grupo de memoria",
"volumeUsage": "Volumen utilizado",
"invalid": "No válido"
},
"deluge": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
"downloadstation": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
}, },
"sonarr": { "sonarr": {
"wanted": "Buscando", "wanted": "Buscando",
"queued": "En cola", "queued": "En cola",
"series": "Series", "series": "Serie",
"queue": "Poner a la cola", "queue": "En cola",
"unknown": "Desconocido" "unknown": "Desconocido"
}, },
"radarr": { "radarr": {
"wanted": "Buscando", "wanted": "Buscando",
"missing": "Faltan",
"queued": "En cola", "queued": "En cola",
"movies": "Películas", "movies": "Películas",
"missing": "Faltan", "queue": "En cola",
"queue": "Poner a la cola",
"unknown": "Desconocido" "unknown": "Desconocido"
}, },
"lidarr": {
"wanted": "Buscando",
"queued": "En cola",
"artists": "Artistas"
},
"readarr": { "readarr": {
"wanted": "Buscando", "wanted": "Buscando",
"queued": "En cola", "queued": "En cola",
"books": "Libros" "books": "Libros"
}, },
"bazarr": {
"missingEpisodes": "Episodios perdidos",
"missingMovies": "Películas perdidas"
},
"ombi": { "ombi": {
"pending": "Pendiente", "pending": "Pendiente",
"approved": "Aprobado", "approved": "Aprobado",
@@ -94,54 +235,74 @@
"approved": "Aprobado", "approved": "Aprobado",
"available": "Disponible" "available": "Disponible"
}, },
"overseerr": {
"pending": "Pendiente",
"processing": "Procesando",
"approved": "Aprobado",
"available": "Disponible"
},
"pialert": {
"total": "Total",
"connected": "Conectado",
"new_devices": "Nuevos dispositivos",
"down_alerts": "Alertas"
},
"pihole": { "pihole": {
"queries": "Consultas", "queries": "Consultas",
"blocked": "Bloqueado", "blocked": "Bloqueado",
"gravity": "Gravedad", "blocked_percent": "% bloqueado",
"blocked_percent": "% bloqueado" "gravity": "Gravedad"
},
"adguard": {
"queries": "Consultas",
"blocked": "Bloqueado",
"filtered": "Filtrado",
"latency": "Latencia"
}, },
"speedtest": { "speedtest": {
"upload": "Subida", "upload": "Subida",
"download": "Bajada", "download": "Descarga",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
"running": "En ejecución", "running": "Ejecutando",
"stopped": "Detenido", "stopped": "Detenido",
"total": "Total" "total": "Total"
}, },
"tailscale": {
"address": "Dirección",
"expires": "Caduca en",
"never": "Nunca",
"last_seen": "Visto por última vez",
"now": "Ahora",
"years": "{{number}}años",
"weeks": "{{number}}semanas",
"days": "{{number}}días",
"hours": "{{number}}horas",
"minutes": "{{number}}minutos",
"seconds": "{{number}}segundos",
"ago": "Hace {{value}}"
},
"tdarr": {
"queue": "En cola",
"processed": "Procesado",
"errored": "Error",
"saved": "Guardado"
},
"traefik": { "traefik": {
"routers": "Enrutadores", "routers": "Enrutadores",
"services": "Servicios", "services": "Servicios",
"middleware": "Software intermedio" "middleware": "Software intermedio"
}, },
"navidrome": {
"nothing_streaming": "Sin transmisiones activas",
"please_wait": "Espere por favor"
},
"npm": { "npm": {
"enabled": "Activado", "enabled": "Activado",
"disabled": "Desactivado", "disabled": "Desactivado",
"total": "Total" "total": "Total"
}, },
"weather": {
"current": "Ubicación actual",
"allow": "Clic para permitir",
"updating": "Actualizando",
"wait": "Espera, por favor"
},
"overseerr": {
"pending": "Pendiente",
"approved": "Aprobado",
"available": "Disponible",
"processing": "Procesando"
},
"sabnzbd": {
"rate": "Tasa",
"queue": "En cola",
"timeleft": "Tiempo restante"
},
"nzbget": {
"rate": "Tasa",
"remaining": "Restante",
"downloaded": "Descargado"
},
"coinmarketcap": { "coinmarketcap": {
"configure": "Configurar una o más criptomonedas para rastrear", "configure": "Configurar una o más criptomonedas para rastrear",
"1hour": "1 Hora", "1hour": "1 Hora",
@@ -161,47 +322,36 @@
"numberOfFailGrabs": "Capturas fallidas", "numberOfFailGrabs": "Capturas fallidas",
"numberOfFailQueries": "Consultas fallidas" "numberOfFailQueries": "Consultas fallidas"
}, },
"transmission": {
"download": "Bajada",
"upload": "Subida",
"leech": "Compañeros",
"seed": "Semillas"
},
"jackett": { "jackett": {
"configured": "Configurado", "configured": "Configurado",
"errored": "Con errores" "errored": "Error"
}, },
"bazarr": { "strelaysrv": {
"missingEpisodes": "Episodios perdidos", "numActiveSessions": "Sesiones",
"missingMovies": "Películas perdidas" "numConnections": "Conexiones",
}, "dataRelayed": "Retransmitido",
"lidarr": { "transferRate": "Tasa"
"queued": "En cola",
"wanted": "Buscando",
"artists": "Artistas"
},
"adguard": {
"queries": "Consultas",
"blocked": "Bloqueado",
"filtered": "Filtrado",
"latency": "Latencia"
},
"qbittorrent": {
"download": "Bajada",
"upload": "Subida",
"leech": "Pares",
"seed": "Semillas"
}, },
"mastodon": { "mastodon": {
"user_count": "Usuarios", "user_count": "Usuarios",
"status_count": "Publicaciones", "status_count": "Publicaciones",
"domain_count": "Dominios" "domain_count": "Dominios"
}, },
"strelaysrv": { "medusa": {
"numActiveSessions": "Sesiones", "wanted": "Buscando",
"numConnections": "Conexiones", "queued": "En cola",
"dataRelayed": "Retransmitido", "series": "Serie"
"transferRate": "Velocidad" },
"minecraft": {
"players": "Jugadores",
"version": "Versión",
"status": "Estado",
"up": "En línea",
"down": "Desconectado"
},
"miniflux": {
"read": "Leer",
"unread": "Sin leer"
}, },
"authentik": { "authentik": {
"users": "Usuarios", "users": "Usuarios",
@@ -209,73 +359,54 @@
"failedLoginsLast24H": "Inicios de sesión fallidos (24h)" "failedLoginsLast24H": "Inicios de sesión fallidos (24h)"
}, },
"proxmox": { "proxmox": {
"mem": "Memoria", "mem": "MEM",
"cpu": "Procesador", "cpu": "CPU",
"lxc": "Contenedores Linux", "lxc": "Contenedores Linux",
"vms": "Máquinas Virtuales" "vms": "Máquinas Virtuales"
}, },
"unifi": {
"up": "LEVANTADO",
"users": "Usuarios",
"uptime": "Tiempo de actividad",
"days": "Días",
"wan": "WAN",
"lan_users": "Usuarios LAN",
"wlan_users": "Usuarios WLAN",
"down": "CAÍDO",
"wait": "Espera por favor",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Dispositivos",
"lan_devices": "Dispositivos LAN",
"wlan_devices": "Dispositivos WLAN",
"empty_data": "Se desconoce el estado del subsistema"
},
"plex": {
"streams": "Transmisiones activas",
"movies": "Películas",
"tv": "Series",
"albums": "Álbumes"
},
"glances": { "glances": {
"cpu": "Procesador", "cpu": "CPU",
"wait": "Espera por favor", "load": "Carga",
"temp": "TEMPORAL", "wait": "Espera, por favor",
"uptime": "ARRIBA", "temp": "TEMP",
"days": "Días", "_temp": "Temperatura",
"hours": "Horas",
"load": "Cargar",
"warn": "Advertir", "warn": "Advertir",
"uptime": "ARRIBA",
"total": "Total", "total": "Total",
"free": "Libre", "free": "Libre",
"used": "Utilizado", "used": "Usado",
"days": "Días",
"hours": "Horas",
"crit": "Crít.", "crit": "Crít.",
"read": "Leer", "read": "Leer",
"write": "Escribir", "write": "Escribir",
"gpu": "GPU", "gpu": "GPU",
"mem": "Memoria", "mem": "Memoria",
"swap": "Intercambiar", "swap": "Intercambiar"
"_temp": "Temperatura"
}, },
"changedetectionio": { "quicklaunch": {
"totalObserved": "Total Observados", "bookmark": "Marcadores",
"diffsDetected": "Diferencias detectadas" "service": "Servicio",
"search": "Buscar",
"custom": "Personalizado",
"visit": "Visita",
"url": "Enlace"
}, },
"wmo": { "wmo": {
"48-night": "Niebla",
"51-day": "Llovizna ligera",
"51-night": "Llovizna ligera",
"2-day": "Parcialmente nuboso",
"0-day": "Soleado", "0-day": "Soleado",
"0-night": "Despejado", "0-night": "Despejado",
"1-day": "Mayormente soleado", "1-day": "Mayormente soleado",
"1-night": "Mayormente despejado", "1-night": "Mayormente despejado",
"2-day": "Parcialmente nuboso",
"2-night": "Parcialmente nuboso", "2-night": "Parcialmente nuboso",
"3-day": "Nublado", "3-day": "Nublado",
"3-night": "Nublado", "3-night": "Nublado",
"45-day": "Niebla", "45-day": "Niebla",
"45-night": "Niebla", "45-night": "Niebla",
"48-day": "Niebla", "48-day": "Niebla",
"48-night": "Niebla",
"51-day": "Llovizna ligera",
"51-night": "Llovizna ligera",
"53-day": "Llovizna", "53-day": "Llovizna",
"53-night": "Llovizna", "53-night": "Llovizna",
"55-day": "Llovizna pesada", "55-day": "Llovizna pesada",
@@ -286,13 +417,13 @@
"57-night": "Llovizna helada", "57-night": "Llovizna helada",
"61-day": "Lluvia ligera", "61-day": "Lluvia ligera",
"61-night": "Lluvia ligera", "61-night": "Lluvia ligera",
"67-day": "Granizo",
"63-day": "Lluvia", "63-day": "Lluvia",
"63-night": "Lluvia", "63-night": "Lluvia",
"65-day": "Chubascos", "65-day": "Chubascos",
"65-night": "Chubascos", "65-night": "Chubascos",
"66-day": "Granizo", "66-day": "Granizo",
"66-night": "Granizo", "66-night": "Granizo",
"67-day": "Granizo",
"67-night": "Granizo", "67-night": "Granizo",
"71-day": "Nevada Leve", "71-day": "Nevada Leve",
"71-night": "Nevada Leve", "71-night": "Nevada Leve",
@@ -319,38 +450,40 @@
"99-day": "Tormenta con granizo", "99-day": "Tormenta con granizo",
"99-night": "Tormenta con granizo" "99-night": "Tormenta con granizo"
}, },
"quicklaunch": {
"bookmark": "Marcadores",
"service": "Servicio",
"search": "Buscar",
"custom": "Personalizado",
"visit": "Visita",
"url": "URL"
},
"homebridge": { "homebridge": {
"available_update": "Sistema", "available_update": "Sistema",
"updates": "Actualizaciones", "updates": "Actualizaciones",
"update_available": "Actualización disponible", "update_available": "Actualización disponible",
"up_to_date": "Actualizado", "up_to_date": "Actualizado",
"child_bridges": "Child Bridges", "child_bridges": "Bridges secundarios",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Arriba", "up": "Arriba",
"pending": "Pendiente", "pending": "Pendiente",
"down": "Abajo" "down": "Abajo"
}, },
"healthchecks": {
"new": "Nuevo",
"up": "En línea",
"grace": "En Periodo de Gracia",
"down": "Desconectado",
"paused": "Pausado",
"status": "Estado",
"last_ping": "Último ping",
"never": "Aún no hay pings"
},
"watchtower": {
"containers_scanned": "Escaneado",
"containers_updated": "Actualizado",
"containers_failed": "Fallido"
},
"autobrr": { "autobrr": {
"approvedPushes": "Aprobado", "approvedPushes": "Aprobado",
"rejectedPushes": "Rechazado", "rejectedPushes": "Rechazado",
"filters": "Filtros", "filters": "Filtros",
"indexers": "Indexadores" "indexers": "Indexadores"
}, },
"watchtower": {
"containers_scanned": "Escaneado",
"containers_updated": "Actualizado",
"containers_failed": "Fallido"
},
"tubearchivist": { "tubearchivist": {
"downloads": "Cola", "downloads": "En cola",
"videos": "Vídeos", "videos": "Vídeos",
"channels": "Canales", "channels": "Canales",
"playlists": "Listas de reproducción" "playlists": "Listas de reproducción"
@@ -361,14 +494,10 @@
"alerts": "Alertas", "alerts": "Alertas",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"navidrome": {
"nothing_streaming": "Sin transmisiones activas",
"please_wait": "Espere por favor"
},
"pyload": { "pyload": {
"speed": "Velocidad", "speed": "Velocidad",
"active": "Activo", "active": "Activo",
"queue": "Cola", "queue": "En cola",
"total": "Total" "total": "Total"
}, },
"gluetun": { "gluetun": {
@@ -380,10 +509,6 @@
"channels": "Canales", "channels": "Canales",
"hd": "Alta definición" "hd": "Alta definición"
}, },
"ping": {
"error": "Error",
"ping": "Ping"
},
"scrutiny": { "scrutiny": {
"passed": "Aprobado", "passed": "Aprobado",
"failed": "Fallido", "failed": "Fallido",
@@ -393,53 +518,14 @@
"inbox": "Bandeja de entrada", "inbox": "Bandeja de entrada",
"total": "Total" "total": "Total"
}, },
"deluge": {
"download": "Descarga",
"upload": "Subida",
"leech": "Compañeros",
"seed": "Semillas"
},
"flood": {
"download": "Descarga",
"upload": "Subida",
"leech": "Depender",
"seed": "Semillas"
},
"tdarr": {
"queue": "Cola",
"processed": "Procesado",
"saved": "Guardado",
"errored": "Error"
},
"miniflux": {
"read": "Leer",
"unread": "Sin leer"
},
"nextdns": { "nextdns": {
"wait": "Espera, por favor", "wait": "Espere por favor",
"no_devices": "No se reciben datos del dispositivo" "no_devices": "No se reciben datos del dispositivo"
}, },
"common": {
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"omada": {
"connectedAp": "AP conectados",
"activeUser": "Dispositivos activos",
"alerts": "Alertas",
"connectedGateway": "Pasarelas conectadas",
"connectedSwitches": "Interruptores conectados"
},
"downloadstation": {
"download": "Descargar",
"upload": "Subir",
"leech": "Compañeros",
"seed": "Semilla"
},
"mikrotik": { "mikrotik": {
"cpuLoad": "Carga de la CPU", "cpuLoad": "Carga de la CPU",
"memoryUsed": "Memoria utilizada", "memoryUsed": "Memoria utilizada",
"uptime": "Tiempo en funcionamiento", "uptime": "Tiempo de la actividad",
"numberOfLeases": "Alquileres" "numberOfLeases": "Alquileres"
}, },
"xteve": { "xteve": {
@@ -447,6 +533,12 @@
"streams_active": "Transmisiones activas", "streams_active": "Transmisiones activas",
"streams_xepg": "Canales XEPG" "streams_xepg": "Canales XEPG"
}, },
"opendtu": {
"yieldDay": "Hoy",
"absolutePower": "Encender",
"relativePower": "Encender %",
"limit": "Límite"
},
"opnsense": { "opnsense": {
"cpu": "Carga de la CPU", "cpu": "Carga de la CPU",
"memory": "Memoria activa", "memory": "Memoria activa",
@@ -459,25 +551,30 @@
"print_progress": "Progreso", "print_progress": "Progreso",
"layers": "Capas" "layers": "Capas"
}, },
"medusa": {
"wanted": "Querido",
"queued": "A la espera",
"series": "Series"
},
"octoprint": { "octoprint": {
"temp_bed": "Temperatura de la plataforma",
"printer_state": "Estado", "printer_state": "Estado",
"temp_tool": "Temperatura de la herramienta", "temp_tool": "Temperatura de la herramienta",
"temp_bed": "Temperatura de la plataforma",
"job_completion": "Finalización" "job_completion": "Finalización"
}, },
"cloudflared": { "cloudflared": {
"origin_ip": "IP de origen", "origin_ip": "IP de origen",
"status": "Estado" "status": "Estado"
}, },
"pfsense": {
"load": "Promedio de carga",
"memory": "Memoria utilizada",
"wanStatus": "Estado de la WAN",
"up": "Arriba",
"down": "Abajo",
"temp": "Temperatura",
"disk": "Uso del disco",
"wanIP": "IP de la WAN"
},
"proxmoxbackupserver": { "proxmoxbackupserver": {
"cpu_usage": "CPU",
"datastore_usage": "Almacén de datos", "datastore_usage": "Almacén de datos",
"failed_tasks_24h": "Tareas fallidas en 24h", "failed_tasks_24h": "Tareas fallidas en 24h",
"cpu_usage": "CPU",
"memory_usage": "Memoria" "memory_usage": "Memoria"
}, },
"immich": { "immich": {
@@ -489,19 +586,30 @@
"uptimekuma": { "uptimekuma": {
"up": "Páginas web activas", "up": "Páginas web activas",
"down": "Páginas web inactivas", "down": "Páginas web inactivas",
"uptime": "Disponibilidad", "uptime": "Tiempo de la actividad",
"incident": "Incidencia", "incident": "Incidencia",
"m": "m" "m": "Minutos"
},
"atsumeru": {
"series": "Serie",
"archives": "Archivos",
"chapters": "Capítulos",
"categories": "Categorías"
}, },
"komga": { "komga": {
"libraries": "Librerías", "libraries": "Librerías",
"series": "Series", "series": "Serie",
"books": "Libros" "books": "Libros"
}, },
"diskstation": {
"days": "Días",
"uptime": "Tiempo de la actividad",
"volumeAvailable": "Disponible"
},
"mylar": { "mylar": {
"series": "Serie",
"issues": "Cuestiones", "issues": "Cuestiones",
"series": "Series", "wanted": "Buscando"
"wanted": "Buscado"
}, },
"photoprism": { "photoprism": {
"albums": "Álbumes", "albums": "Álbumes",
@@ -509,19 +617,14 @@
"videos": "Vídeos", "videos": "Vídeos",
"people": "Personas" "people": "Personas"
}, },
"diskstation": {
"days": "Días",
"uptime": "Funcionando",
"volumeAvailable": "Disponible"
},
"fileflows": { "fileflows": {
"queue": "Cola", "queue": "En cola",
"processing": "Procesando", "processing": "Procesando",
"processed": "Procesado", "processed": "Procesado",
"time": "Tiempo" "time": "Tiempo"
}, },
"grafana": { "grafana": {
"dashboards": "Dashboards", "dashboards": "Tableros",
"datasources": "Fuentes de datos", "datasources": "Fuentes de datos",
"totalalerts": "Alertas totales", "totalalerts": "Alertas totales",
"alertstriggered": "Alertas activadas" "alertstriggered": "Alertas activadas"
@@ -546,16 +649,6 @@
"total_workers": "Total de trabajadores", "total_workers": "Total de trabajadores",
"records_total": "Duración de la cola" "records_total": "Duración de la cola"
}, },
"healthchecks": {
"new": "Nuevo",
"up": "Conectado",
"down": "Desconectado",
"grace": "En Periodo de Gracia",
"paused": "Pausado",
"status": "Estado",
"last_ping": "Último ping",
"never": "Aún no hay pings"
},
"pterodactyl": { "pterodactyl": {
"servers": "Servidores", "servers": "Servidores",
"nodes": "Nodos" "nodes": "Nodos"
@@ -565,13 +658,6 @@
"targets_down": "Objetivos abajo", "targets_down": "Objetivos abajo",
"targets_total": "Objetivos totales" "targets_total": "Objetivos totales"
}, },
"minecraft": {
"status": "Estado",
"up": "En línea",
"players": "Jugadores",
"version": "Versión",
"down": "Sin conexión"
},
"ghostfolio": { "ghostfolio": {
"gross_percent_today": "Hoy", "gross_percent_today": "Hoy",
"gross_percent_1y": "Un año", "gross_percent_1y": "Un año",
@@ -588,93 +674,26 @@
"lights_on": "Luces encendidas", "lights_on": "Luces encendidas",
"switches_on": "Encendido" "switches_on": "Encendido"
}, },
"freshrss": {
"subscriptions": "Suscripciones",
"unread": "Sin leer"
},
"channelsdvrserver": {
"shows": "Espectáculos",
"recordings": "Grabaciones",
"scheduled": "Programado",
"passes": "Pases"
},
"whatsupdocker": { "whatsupdocker": {
"monitoring": "Supervisión", "monitoring": "Supervisión",
"updates": "Actualizaciones" "updates": "Actualizaciones"
}, },
"tailscale": { "calibreweb": {
"address": "Dirección", "books": "Libros",
"expires": "Caduca en", "authors": "Autores",
"never": "Nunca", "categories": "Categorías",
"last_seen": "Visto por última vez", "series": "Serie"
"now": "Ahora",
"years": "{{number}}años",
"hours": "{{number}}horas",
"minutes": "{{number}}minutos",
"seconds": "{{number}}segundos",
"ago": "Hace {{value}}",
"weeks": "{{number}}semanas",
"days": "{{number}}días"
},
"qnap": {
"cpuUsage": "Uso de la Cpu",
"memUsage": "Uso de la memoria",
"systemTempC": "Temperatura del sistema",
"poolUsage": "Comprobación del uso del grupo de memoria",
"volumeUsage": "Volumen utilizado",
"invalid": "No válido"
},
"pfsense": {
"load": "Promedio de carga",
"memory": "Memoria utilizada",
"wanStatus": "Estado de la WAN",
"up": "Arriba",
"down": "Abajo",
"temp": "Temperatura",
"disk": "Uso del disco",
"wanIP": "IP de la WAN"
},
"caddy": {
"upstreams": "Upstream (desarrollo de software)",
"requests": "Peticiones actuales",
"requests_failed": "Peticiones fallidas"
},
"evcc": {
"pv_power": "Producción",
"battery_soc": "Batería",
"grid_power": "Red",
"home_power": "Consumo",
"charge_power": "Cargador",
"watt_hour": "vatio-hora (Wh)"
},
"pialert": {
"total": "Total",
"connected": "Conectado",
"new_devices": "Nuevos dispositivos",
"down_alerts": "Alertas"
}, },
"jdownloader": { "jdownloader": {
"downloadCount": "Cola", "downloadCount": "En cola",
"downloadSpeed": "Velocidad",
"downloadBytesRemaining": "Restante", "downloadBytesRemaining": "Restante",
"downloadTotalBytes": "Tamaño" "downloadTotalBytes": "Tamaño",
"downloadSpeed": "Velocidad"
}, },
"kavita": { "kavita": {
"seriesCount": "Series", "seriesCount": "Serie",
"totalFiles": "Archivos" "totalFiles": "Archivos"
}, },
"gamedig": {
"name": "Nombre",
"map": "Mapa",
"currentPlayers": "Jugadores actuales",
"players": "Jugadores",
"maxPlayers": "Jugadores máximos",
"bots": "Bots",
"ping": "Ping",
"status": "Estado",
"online": "En línea",
"offline": "Sin conexión"
},
"azuredevops": { "azuredevops": {
"result": "Resultado", "result": "Resultado",
"status": "Estado", "status": "Estado",
@@ -686,7 +705,19 @@
"inProgress": "En curso", "inProgress": "En curso",
"totalPrs": "RP totales", "totalPrs": "RP totales",
"myPrs": "Mis logros", "myPrs": "Mis logros",
"approved": "Aprobados" "approved": "Aprobado"
},
"gamedig": {
"status": "Estado",
"online": "En línea",
"offline": "Desconectado",
"name": "Nombre",
"map": "Mapa",
"currentPlayers": "Jugadores actuales",
"players": "Jugadores",
"maxPlayers": "Jugadores máximos",
"bots": "Bots",
"ping": "Ping"
}, },
"urbackup": { "urbackup": {
"ok": "De acuerdo", "ok": "De acuerdo",
@@ -694,39 +725,27 @@
"noRecent": "Caducado", "noRecent": "Caducado",
"totalUsed": "Almacenamiento usado" "totalUsed": "Almacenamiento usado"
}, },
"openmediavault": {
"running": "Ejecutando",
"downloading": "Descargando",
"total": "Total",
"stopped": "Detenido",
"passed": "Aprobado",
"failed": "Fallido"
},
"mealie": { "mealie": {
"recipes": "Recetas", "recipes": "Recetas",
"users": "Usuarios", "users": "Usuarios",
"categories": "Categorías", "categories": "Categorías",
"tags": "Etiquetas" "tags": "Etiquetas"
}, },
"atsumeru": { "openmediavault": {
"series": "Series", "downloading": "Descargando",
"archives": "Archivos", "total": "Total",
"chapters": "Capítulos", "running": "Ejecutando",
"categories": "Categorías" "stopped": "Detenido",
}, "passed": "Aprobado",
"calibreweb": { "failed": "Fallido"
"books": "Libros",
"authors": "Autores",
"categories": "Categorías",
"series": "Series"
}, },
"uptimerobot": { "uptimerobot": {
"status": "Estado", "status": "Estado",
"uptime": "Tiempo de actividad", "uptime": "Tiempo de la actividad",
"lastDown": "Último periodo de inactividad", "lastDown": "Último periodo de inactividad",
"downDuration": "Tiempo de inactividad", "downDuration": "Tiempo de inactividad",
"sitesUp": "Páginas web con conexión", "sitesUp": "Páginas web activas",
"sitesDown": "Páginas web caídas", "sitesDown": "Páginas web inactivas",
"paused": "Pausado", "paused": "Pausado",
"notyetchecked": "Aún no verificado", "notyetchecked": "Aún no verificado",
"up": "Arriba", "up": "Arriba",
@@ -734,15 +753,9 @@
"down": "Abajo", "down": "Abajo",
"unknown": "Desconocido" "unknown": "Desconocido"
}, },
"opendtu": {
"relativePower": "Encender %",
"yieldDay": "Hoy",
"limit": "Límite",
"absolutePower": "Encender"
},
"calendar": { "calendar": {
"physicalRelease": "Lanzamiento en físico",
"inCinemas": "En cine", "inCinemas": "En cine",
"physicalRelease": "Lanzamiento en físico",
"digitalRelease": "Lanzamiento en digital" "digitalRelease": "Lanzamiento en digital"
} }
} }

View File

@@ -140,7 +140,9 @@
}, },
"ping": { "ping": {
"error": "Errorea", "error": "Errorea",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Playing", "playing": "Playing",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -1,46 +1,90 @@
{ {
"common": {
"bytes": "{{value, bytes}}",
"bits": "{{value, bytes(bits: true)}}",
"bbytes": "{{value, bytes(binary: true)}}",
"bbits": "{{value, bytes(bits: true; binary: true)}}",
"byterate": "{{value, rate(bits: false)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bitrate": "{{value, rate(bits: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"percent": "{{value, percent}}",
"number": "{{value, number}}",
"ms": "{{value, number}}"
},
"widget": { "widget": {
"missing_type": "Type de widget manquant: {{type}}", "missing_type": "Type de widget manquant: {{type}}",
"api_error": "Erreur de l'API", "api_error": "Erreur de l'API",
"status": "Statut",
"information": "Information", "information": "Information",
"status": "Statut",
"url": "URL", "url": "URL",
"raw_error": "Erreur brute", "raw_error": "Erreur brute",
"response_data": "Données de réponse" "response_data": "Données de réponse"
}, },
"weather": {
"current": "Localisation actuelle",
"allow": "Cliquez pour autoriser",
"updating": "Mise à jour",
"wait": "Veuillez patienter"
},
"search": { "search": {
"placeholder": "Recherche…" "placeholder": "Recherche…"
}, },
"resources": { "resources": {
"cpu": "CPU",
"mem": "MÉM",
"total": "Total", "total": "Total",
"free": "Libre", "free": "Libre",
"used": "Utilisé", "used": "Utilisé",
"load": "Charge", "load": "Charge",
"cpu": "CPU",
"mem": "MÉM",
"max": "Max",
"temp": "TEMP", "temp": "TEMP",
"max": "Max",
"uptime": "UP", "uptime": "UP",
"months": "mo", "months": "mo",
"days": "d", "days": "d",
"hours": "h", "hours": "h",
"minutes": "mn" "minutes": "mn"
}, },
"unifi": {
"users": "Utilisateurs",
"uptime": "Disponibilité du système",
"days": "Jours",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Équipt.",
"lan_devices": "Équipt. LAN",
"wlan_devices": "Équipt. WLAN",
"lan_users": "Utilisateurs LAN",
"wlan_users": "Utilisateurs WLAN",
"up": "UP",
"down": "DOWN",
"wait": "Veuillez patienter",
"empty_data": "Statut sous-système inconnu"
},
"docker": { "docker": {
"rx": "Rx", "rx": "Rx",
"tx": "Tx", "tx": "Tx",
"mem": "Mém", "mem": "MÉM",
"cpu": "Cpu", "cpu": "CPU",
"running": "Démarré",
"offline": "Hors ligne", "offline": "Hors ligne",
"error": "Erreur", "error": "Erreur",
"unknown": "Inconnu", "unknown": "Inconnu",
"running": "Démarré", "healthy": "Fonctionnel",
"starting": "Démarrage", "starting": "Démarrage",
"unhealthy": "Dysfonctionnement", "unhealthy": "Dysfonctionnement",
"not_found": "Inconnu", "not_found": "Inconnu",
"exited": "Arrêté", "exited": "Arrêté",
"partial": "Partiel", "partial": "Partiel"
"healthy": "Fonctionnel" },
"ping": {
"http_status": "État HTTP",
"error": "Erreur",
"ping": "Ping",
"down": "Down",
"up": "Up",
"not_available": "Non disponible"
}, },
"emby": { "emby": {
"playing": "En lecture", "playing": "En lecture",
@@ -52,6 +96,39 @@
"episodes": "Épisodes", "episodes": "Épisodes",
"songs": "Musique" "songs": "Musique"
}, },
"evcc": {
"pv_power": "Production",
"battery_soc": "Batterie",
"grid_power": "Grille",
"home_power": "Consommation",
"charge_power": "Chargeur",
"watt_hour": "Wh"
},
"flood": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"freshrss": {
"subscriptions": "Abonnements",
"unread": "Non lu"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Demandes en cours",
"requests_failed": "Demandes échouées"
},
"changedetectionio": {
"totalObserved": "Total Observé",
"diffsDetected": "Diffs Detectées"
},
"channelsdvrserver": {
"shows": "Affichages",
"recordings": "Enregistrements",
"scheduled": "Planifié",
"passes": "Passes"
},
"tautulli": { "tautulli": {
"playing": "En lecture", "playing": "En lecture",
"transcoding": "Transcodage", "transcoding": "Transcodage",
@@ -59,31 +136,95 @@
"no_active": "Aucun flux actif", "no_active": "Aucun flux actif",
"plex_connection_error": "Vérifier la connexion à Plex" "plex_connection_error": "Vérifier la connexion à Plex"
}, },
"omada": {
"connectedAp": "APs connectées",
"activeUser": "Équipts actifs",
"alerts": "Alertes",
"connectedGateway": "Passerelles connectées",
"connectedSwitches": "Switches connectés"
},
"nzbget": {
"rate": "Débit",
"remaining": "Restant",
"downloaded": "Téléchargé"
},
"plex": {
"streams": "Flux actif",
"albums": "Albums",
"movies": "Films",
"tv": "Séries TV"
},
"sabnzbd": {
"rate": "Débit",
"queue": "En attente",
"timeleft": "Temps restant"
},
"rutorrent": { "rutorrent": {
"active": "Actif", "active": "Actif",
"upload": "Envoi", "upload": "Envoi",
"download": "Réception" "download": "Récep."
},
"transmission": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"qbittorrent": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"qnap": {
"cpuUsage": "Cpu",
"memUsage": "Mém",
"systemTempC": "Temp",
"poolUsage": "Pool",
"volumeUsage": "Volume",
"invalid": "Invalide"
},
"deluge": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"downloadstation": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
}, },
"sonarr": { "sonarr": {
"wanted": "Demande", "wanted": "Demande",
"queued": "Attente", "queued": "Attente",
"series": "Séries", "series": "Séries TV",
"queue": "Attente", "queue": "En attente",
"unknown": "Inconnu" "unknown": "Inconnu"
}, },
"radarr": { "radarr": {
"wanted": "Demande", "wanted": "Demande",
"missing": "Manquant",
"queued": "Attente", "queued": "Attente",
"movies": "Films", "movies": "Films",
"missing": "Manquant", "queue": "En attente",
"queue": "Attente",
"unknown": "Inconnu" "unknown": "Inconnu"
}, },
"lidarr": {
"wanted": "Demande",
"queued": "Attente",
"artists": "Artistes"
},
"readarr": { "readarr": {
"wanted": "Demande", "wanted": "Demande",
"queued": "Attente", "queued": "Attente",
"books": "Livres" "books": "Livres"
}, },
"bazarr": {
"missingEpisodes": "Épisodes manquants",
"missingMovies": "Films manquants"
},
"ombi": { "ombi": {
"pending": "En attente", "pending": "En attente",
"approved": "Validé", "approved": "Validé",
@@ -94,11 +235,29 @@
"approved": "Validé", "approved": "Validé",
"available": "Disponible" "available": "Disponible"
}, },
"overseerr": {
"pending": "En attente",
"processing": "Traitement",
"approved": "Validé",
"available": "Disponible"
},
"pialert": {
"total": "Total",
"connected": "Connecté",
"new_devices": "Nouvel Appareil",
"down_alerts": "Alertes"
},
"pihole": { "pihole": {
"queries": "Requêtes", "queries": "Requêtes",
"blocked": "Bloqué", "blocked": "Bloqué",
"gravity": "Listes dom. bloqués", "blocked_percent": "Bloqué %",
"blocked_percent": "Bloqué %" "gravity": "Listes dom. bloqués"
},
"adguard": {
"queries": "Requêtes",
"blocked": "Bloqué",
"filtered": "Filtrées",
"latency": "Latence"
}, },
"speedtest": { "speedtest": {
"upload": "Envoi", "upload": "Envoi",
@@ -110,38 +269,40 @@
"stopped": "Arrêté", "stopped": "Arrêté",
"total": "Total" "total": "Total"
}, },
"tailscale": {
"address": "Adresse",
"expires": "Expire",
"never": "Jamais",
"last_seen": "Vu pour la dernière fois",
"now": "Maintenant",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "Il y a {{value}}"
},
"tdarr": {
"queue": "En attente",
"processed": "Traité",
"errored": "En erreur",
"saved": "Libéré"
},
"traefik": { "traefik": {
"routers": "Routeurs", "routers": "Routeurs",
"services": "Services", "services": "Services",
"middleware": "Middleware" "middleware": "Middleware"
}, },
"navidrome": {
"nothing_streaming": "Aucun flux actif",
"please_wait": "Merci de patienter"
},
"npm": { "npm": {
"enabled": "Activé", "enabled": "Activé",
"disabled": "Désactivé", "disabled": "Désactivé",
"total": "Total" "total": "Total"
}, },
"weather": {
"current": "Localisation actuelle",
"allow": "Cliquez pour autoriser",
"updating": "Mise à jour",
"wait": "Veuillez patienter"
},
"overseerr": {
"pending": "Attente",
"approved": "Demande",
"available": "Disponible",
"processing": "Traitement"
},
"sabnzbd": {
"rate": "Débit",
"queue": "En attente",
"timeleft": "Temps restant"
},
"nzbget": {
"remaining": "Restant",
"downloaded": "Téléchargé",
"rate": "Débit"
},
"coinmarketcap": { "coinmarketcap": {
"configure": "Configurer une ou plusieurs crypto-monnaies à suivre", "configure": "Configurer une ou plusieurs crypto-monnaies à suivre",
"1hour": "1 Heure", "1hour": "1 Heure",
@@ -157,123 +318,89 @@
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexeur", "enableIndexers": "Indexeur",
"numberOfGrabs": "Capture", "numberOfGrabs": "Capture",
"numberOfQueries": "Demande", "numberOfQueries": "Requêtes",
"numberOfFailGrabs": "Capt. échouée", "numberOfFailGrabs": "Capt. échouée",
"numberOfFailQueries": "Dem. échouée" "numberOfFailQueries": "Dem. échouée"
}, },
"transmission": {
"download": "Réception",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"jackett": { "jackett": {
"configured": "Configuré", "configured": "Configuré",
"errored": "En erreur" "errored": "En erreur"
}, },
"bazarr": {
"missingEpisodes": "Épisodes manquants",
"missingMovies": "Films manquants"
},
"lidarr": {
"wanted": "Demandé",
"queued": "En queue",
"artists": "Artistes"
},
"adguard": {
"queries": "Requêtes",
"blocked": "Bloquées",
"filtered": "Filtrées",
"latency": "Latence"
},
"qbittorrent": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"mastodon": {
"user_count": "Utilisateurs",
"status_count": "Messages",
"domain_count": "Domaines"
},
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "Sessions",
"numConnections": "Cnx", "numConnections": "Cnx",
"dataRelayed": "Relayé", "dataRelayed": "Relayé",
"transferRate": "Débit" "transferRate": "Débit"
}, },
"mastodon": {
"user_count": "Utilisateurs",
"status_count": "Messages",
"domain_count": "Domaines"
},
"medusa": {
"wanted": "Demande",
"queued": "Attente",
"series": "Séries TV"
},
"minecraft": {
"players": "Joueurs",
"version": "Version",
"status": "Statut",
"up": "En ligne",
"down": "Hors ligne"
},
"miniflux": {
"read": "Lu",
"unread": "Non lu"
},
"authentik": { "authentik": {
"users": "Utilisateurs", "users": "Utilisateurs",
"loginsLast24H": "Cnx. (24h)", "loginsLast24H": "Cnx. (24h)",
"failedLoginsLast24H": "Cnx. échouées (24h)" "failedLoginsLast24H": "Cnx. échouées (24h)"
}, },
"proxmox": { "proxmox": {
"mem": "Mém", "mem": "MÉM",
"cpu": "Cpu", "cpu": "CPU",
"lxc": "LxC", "lxc": "LxC",
"vms": "VMs" "vms": "VMs"
}, },
"unifi": {
"users": "Utilisateurs",
"uptime": "Disponibilité du système",
"days": "Jours",
"wan": "WAN",
"lan_users": "Utilisateurs LAN",
"wlan_users": "Utilisateurs WLAN",
"up": "UP",
"down": "DOWN",
"wait": "Merci de patienter",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Équipt.",
"lan_devices": "Équipt. LAN",
"wlan_devices": "Équipt. WLAN",
"empty_data": "Statut sous-système inconnu"
},
"plex": {
"streams": "Flux actif",
"movies": "Films",
"tv": "Séries TV",
"albums": "Albums"
},
"glances": { "glances": {
"cpu": "Cpu", "cpu": "CPU",
"wait": "Merci de patienter",
"temp": "Temp",
"uptime": "Up",
"days": "j",
"hours": "h",
"load": "Charge", "load": "Charge",
"wait": "Veuillez patienter",
"temp": "TEMP",
"_temp": "Temp",
"warn": "Alerte", "warn": "Alerte",
"uptime": "UP",
"total": "Total", "total": "Total",
"free": "Libre", "free": "Libre",
"used": "Utilisé", "used": "Utilisé",
"days": "d",
"hours": "h",
"crit": "Crit.", "crit": "Crit.",
"read": "Lect.", "read": "Lu",
"write": "Écrit.", "write": "Écrit.",
"gpu": "GPU", "gpu": "GPU",
"mem": "Mém.", "mem": "Mém.",
"swap": "Swap", "swap": "Swap"
"_temp": "Temp"
}, },
"changedetectionio": { "quicklaunch": {
"totalObserved": "Total Observé", "bookmark": "Signet",
"diffsDetected": "Diffs Detectées" "service": "Service",
"search": "Recherche",
"custom": "Personnalisé",
"visit": "Aller vers",
"url": "URL"
}, },
"wmo": { "wmo": {
"0-day": "Ensoleillé",
"0-night": "Ciel clair",
"1-day": "Principalement ensoleillé", "1-day": "Principalement ensoleillé",
"1-night": "Principalement clair", "1-night": "Principalement clair",
"2-day": "Partiellement couvert", "2-day": "Partiellement couvert",
"2-night": "Partiellement couvert", "2-night": "Partiellement couvert",
"3-day": "Couvert", "3-day": "Couvert",
"3-night": "Couvert", "3-night": "Couvert",
"63-night": "Pluie",
"65-day": "Pluie forte",
"85-day": "Averses de neige",
"85-night": "Averses de neige",
"86-day": "Averses de neige",
"0-night": "Ciel clair",
"45-day": "Brumeux", "45-day": "Brumeux",
"45-night": "Brumeux", "45-night": "Brumeux",
"48-day": "Brumeux", "48-day": "Brumeux",
@@ -291,6 +418,8 @@
"61-day": "Pluie légère", "61-day": "Pluie légère",
"61-night": "Pluie légère", "61-night": "Pluie légère",
"63-day": "Pluie", "63-day": "Pluie",
"63-night": "Pluie",
"65-day": "Pluie forte",
"65-night": "Pluie forte", "65-night": "Pluie forte",
"66-day": "Pluie verglaçante", "66-day": "Pluie verglaçante",
"66-night": "Pluie verglaçante", "66-night": "Pluie verglaçante",
@@ -310,22 +439,16 @@
"81-night": "Averses", "81-night": "Averses",
"82-day": "Averses fortes", "82-day": "Averses fortes",
"82-night": "Averses fortes", "82-night": "Averses fortes",
"85-day": "Averses de neige",
"85-night": "Averses de neige",
"86-day": "Averses de neige",
"86-night": "Averses de neige", "86-night": "Averses de neige",
"95-day": "Orage", "95-day": "Orage",
"95-night": "Orage", "95-night": "Orage",
"96-day": "Orage avec grêle", "96-day": "Orage avec grêle",
"96-night": "Orage avec grêle", "96-night": "Orage avec grêle",
"99-day": "Orage avec grêle", "99-day": "Orage avec grêle",
"99-night": "Orage avec grêle", "99-night": "Orage avec grêle"
"0-day": "Ensoleillé"
},
"quicklaunch": {
"bookmark": "Signet",
"service": "Service",
"search": "Recherche",
"custom": "Personnalisé",
"visit": "Aller vers",
"url": "URL"
}, },
"homebridge": { "homebridge": {
"available_update": "Système", "available_update": "Système",
@@ -335,22 +458,32 @@
"child_bridges": "Child Bridges", "child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Up", "up": "Up",
"pending": "Pending", "pending": "En attente",
"down": "Down" "down": "Down"
}, },
"autobrr": { "healthchecks": {
"approvedPushes": "Approuvé", "new": "Nouveau",
"rejectedPushes": "Rejeté", "up": "En ligne",
"filters": "Filtres", "grace": "En Période de Grâce",
"indexers": "Indexeur" "down": "Hors ligne",
"paused": "En Pause",
"status": "Statut",
"last_ping": "Dernier Ping",
"never": "Pas de Ping"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Scanné", "containers_scanned": "Scanné",
"containers_updated": "Mis à jour", "containers_updated": "Mis à jour",
"containers_failed": "Échoué" "containers_failed": "Échoué"
}, },
"autobrr": {
"approvedPushes": "Validé",
"rejectedPushes": "Rejeté",
"filters": "Filtres",
"indexers": "Indexeur"
},
"tubearchivist": { "tubearchivist": {
"downloads": "Queue", "downloads": "En attente",
"videos": "Vidéos", "videos": "Vidéos",
"channels": "Chaînes", "channels": "Chaînes",
"playlists": "Playlists" "playlists": "Playlists"
@@ -361,14 +494,10 @@
"alerts": "Alertes", "alerts": "Alertes",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"navidrome": {
"nothing_streaming": "Aucun flux actif",
"please_wait": "Merci de patienter"
},
"pyload": { "pyload": {
"speed": "Débit", "speed": "Débit",
"active": "Actif", "active": "Actif",
"queue": "Queue", "queue": "En attente",
"total": "Total" "total": "Total"
}, },
"gluetun": { "gluetun": {
@@ -377,13 +506,9 @@
"country": "Pays" "country": "Pays"
}, },
"hdhomerun": { "hdhomerun": {
"channels": "Canaux", "channels": "Chaînes",
"hd": "HD" "hd": "HD"
}, },
"ping": {
"error": "Erreur",
"ping": "Ping"
},
"scrutiny": { "scrutiny": {
"passed": "Réussi", "passed": "Réussi",
"failed": "Échoué", "failed": "Échoué",
@@ -393,53 +518,14 @@
"inbox": "Boîte de réception", "inbox": "Boîte de réception",
"total": "Total" "total": "Total"
}, },
"deluge": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"flood": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"tdarr": {
"queue": "À traiter",
"processed": "Traité",
"errored": "En erreur",
"saved": "Libéré"
},
"miniflux": {
"read": "Lu",
"unread": "Non lu"
},
"nextdns": { "nextdns": {
"wait": "Patientez...", "wait": "Merci de patienter",
"no_devices": "Aucune donnée d'appareil reçue" "no_devices": "Aucune donnée d'appareil reçue"
}, },
"common": {
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}"
},
"omada": {
"connectedAp": "APs connectées",
"activeUser": "Équipts actifs",
"alerts": "Alertes",
"connectedGateway": "Passerelles connectées",
"connectedSwitches": "Switches connectés"
},
"downloadstation": {
"download": "Récep.",
"upload": "Envoi",
"leech": "Leech",
"seed": "Seed"
},
"mikrotik": { "mikrotik": {
"cpuLoad": "Charge CPU", "cpuLoad": "Charge CPU",
"memoryUsed": "Mém. Utilisée", "memoryUsed": "Mém. Utilisée",
"uptime": "Disponibilité", "uptime": "Démarré depuis",
"numberOfLeases": "Baux" "numberOfLeases": "Baux"
}, },
"xteve": { "xteve": {
@@ -447,6 +533,12 @@
"streams_active": "Flux actif", "streams_active": "Flux actif",
"streams_xepg": "Canal XEPG" "streams_xepg": "Canal XEPG"
}, },
"opendtu": {
"yieldDay": "Aujourd'hui",
"absolutePower": "Puissance",
"relativePower": "Puissance %",
"limit": "Limite"
},
"opnsense": { "opnsense": {
"cpu": "Charge CPU", "cpu": "Charge CPU",
"memory": "Mém. Utilisée", "memory": "Mém. Utilisée",
@@ -459,13 +551,8 @@
"print_progress": "Progression", "print_progress": "Progression",
"layers": "Couches" "layers": "Couches"
}, },
"medusa": {
"wanted": "Demande",
"queued": "En attente",
"series": "Séries"
},
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "Statut",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Achèvement" "job_completion": "Achèvement"
@@ -474,6 +561,16 @@
"origin_ip": "IP Publique", "origin_ip": "IP Publique",
"status": "Statut" "status": "Statut"
}, },
"pfsense": {
"load": "Charge moy.",
"memory": "Util. Mém.",
"wanStatus": "Statut WAN",
"up": "Up",
"down": "Down",
"temp": "Temp",
"disk": "Util. Disque",
"wanIP": "IP WAN"
},
"proxmoxbackupserver": { "proxmoxbackupserver": {
"datastore_usage": "Datastore", "datastore_usage": "Datastore",
"failed_tasks_24h": "Tâches échouées 24h", "failed_tasks_24h": "Tâches échouées 24h",
@@ -489,17 +586,28 @@
"uptimekuma": { "uptimekuma": {
"up": "En ligne", "up": "En ligne",
"down": "Hors ligne", "down": "Hors ligne",
"uptime": "Dispo.", "uptime": "Démarré depuis",
"incident": "Incident", "incident": "Incident",
"m": "m" "m": "mn"
},
"atsumeru": {
"series": "Séries TV",
"archives": "Archives",
"chapters": "Chapitres",
"categories": "Catégories"
}, },
"komga": { "komga": {
"libraries": "Librairies", "libraries": "Librairies",
"series": "Séries", "series": "Séries TV",
"books": "Livres" "books": "Livres"
}, },
"diskstation": {
"days": "Jours",
"uptime": "Démarré depuis",
"volumeAvailable": "Disponible"
},
"mylar": { "mylar": {
"series": "Séries", "series": "Séries TV",
"issues": "Issues", "issues": "Issues",
"wanted": "Demande" "wanted": "Demande"
}, },
@@ -509,13 +617,8 @@
"videos": "Vidéos", "videos": "Vidéos",
"people": "Personnes" "people": "Personnes"
}, },
"diskstation": {
"days": "Jours",
"uptime": "Fonctionnement",
"volumeAvailable": "Disponible"
},
"fileflows": { "fileflows": {
"queue": "À traiter", "queue": "En attente",
"processing": "Traitement", "processing": "Traitement",
"processed": "Traité", "processed": "Traité",
"time": "Temps" "time": "Temps"
@@ -527,10 +630,10 @@
"alertstriggered": "Alertes déclenchées" "alertstriggered": "Alertes déclenchées"
}, },
"nextcloud": { "nextcloud": {
"freespace": "Libre",
"activeusers": "Utilisateurs Actifs",
"cpuload": "Charge Cpu", "cpuload": "Charge Cpu",
"memoryusage": "Utilisation Mémoire", "memoryusage": "Utilisation Mémoire",
"freespace": "Libre",
"activeusers": "Utilisateurs Actifs",
"numfiles": "Fichiers", "numfiles": "Fichiers",
"numshares": "Partages" "numshares": "Partages"
}, },
@@ -539,23 +642,13 @@
"size": "Taille", "size": "Taille",
"lastrun": "Dernière exécution", "lastrun": "Dernière exécution",
"nextrun": "Prochaine exécution", "nextrun": "Prochaine exécution",
"failed": "En erreur" "failed": "Échoué"
}, },
"unmanic": { "unmanic": {
"active_workers": "En cours", "active_workers": "En cours",
"total_workers": "Total", "total_workers": "Total",
"records_total": "En attente" "records_total": "En attente"
}, },
"healthchecks": {
"new": "Nouveau",
"up": "En ligne",
"grace": "En Période de Grâce",
"down": "Hors ligne",
"paused": "En Pause",
"status": "Statut",
"last_ping": "Dernier Ping",
"never": "Pas de Ping"
},
"pterodactyl": { "pterodactyl": {
"servers": "Serveurs", "servers": "Serveurs",
"nodes": "Nœuds" "nodes": "Nœuds"
@@ -565,13 +658,6 @@
"targets_down": "Targets Down", "targets_down": "Targets Down",
"targets_total": "Total Targets" "targets_total": "Total Targets"
}, },
"minecraft": {
"players": "Joueurs",
"version": "Version",
"status": "Statut",
"up": "En ligne",
"down": "Hors ligne"
},
"ghostfolio": { "ghostfolio": {
"gross_percent_today": "Aujourd'hui", "gross_percent_today": "Aujourd'hui",
"gross_percent_1y": "Un an", "gross_percent_1y": "Un an",
@@ -588,93 +674,26 @@
"lights_on": "Lumières allumées", "lights_on": "Lumières allumées",
"switches_on": "Commutateur On" "switches_on": "Commutateur On"
}, },
"freshrss": {
"unread": "Non lu",
"subscriptions": "Abonnements"
},
"channelsdvrserver": {
"shows": "Affichages",
"recordings": "Enregistrements",
"scheduled": "Planifié",
"passes": "Passes"
},
"whatsupdocker": { "whatsupdocker": {
"monitoring": "Conteneurs", "monitoring": "Conteneurs",
"updates": "Mises à jour" "updates": "Mises à jour"
}, },
"tailscale": { "calibreweb": {
"address": "Adresse", "books": "Livres",
"expires": "Expire", "authors": "Auteurs",
"never": "Jamais", "categories": "Catégories",
"last_seen": "Vu pour la dernière fois", "series": "Séries TV"
"now": "Maintenant",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "Il y a {{value}}"
},
"qnap": {
"cpuUsage": "Cpu",
"memUsage": "Mém",
"systemTempC": "Temp",
"poolUsage": "Pool",
"volumeUsage": "Volume",
"invalid": "Invalide"
},
"pfsense": {
"load": "Charge moy.",
"memory": "Util. Mém.",
"wanStatus": "Statut WAN",
"up": "Up",
"down": "Down",
"temp": "Temp",
"disk": "Util. Disque",
"wanIP": "IP WAN"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Demandes en cours",
"requests_failed": "Demandes échouées"
},
"evcc": {
"pv_power": "Production",
"battery_soc": "Batterie",
"grid_power": "Grille",
"home_power": "Consommation",
"charge_power": "Chargeur",
"watt_hour": "Wh"
},
"pialert": {
"total": "Total",
"connected": "Connecté",
"new_devices": "Nouvel Appareil",
"down_alerts": "Alertes"
}, },
"jdownloader": { "jdownloader": {
"downloadCount": "Total en attente", "downloadCount": "En attente",
"downloadSpeed": "Vitesse de téléchargement",
"downloadBytesRemaining": "Restant", "downloadBytesRemaining": "Restant",
"downloadTotalBytes": "Taille" "downloadTotalBytes": "Taille",
"downloadSpeed": "Débit"
}, },
"kavita": { "kavita": {
"seriesCount": "Séries", "seriesCount": "Séries TV",
"totalFiles": "Fichiers" "totalFiles": "Fichiers"
}, },
"gamedig": {
"name": "Nom",
"map": "Carte",
"currentPlayers": "Joueurs actuels",
"players": "Joueurs",
"maxPlayers": "Joueurs max",
"bots": "Bots",
"ping": "Ping",
"status": "Statut",
"online": "En ligne",
"offline": "Hors ligne"
},
"azuredevops": { "azuredevops": {
"result": "Résultat", "result": "Résultat",
"status": "Statut", "status": "Statut",
@@ -686,7 +705,19 @@
"inProgress": "En cours", "inProgress": "En cours",
"totalPrs": "PRs Total", "totalPrs": "PRs Total",
"myPrs": "Mes PRs", "myPrs": "Mes PRs",
"approved": "Approuvé" "approved": "Validé"
},
"gamedig": {
"status": "Statut",
"online": "En ligne",
"offline": "Hors ligne",
"name": "Nom",
"map": "Carte",
"currentPlayers": "Joueurs actuels",
"players": "Joueurs",
"maxPlayers": "Joueurs max",
"bots": "Bots",
"ping": "Ping"
}, },
"urbackup": { "urbackup": {
"ok": "Ok", "ok": "Ok",
@@ -694,6 +725,12 @@
"noRecent": "Obsolète", "noRecent": "Obsolète",
"totalUsed": "Esp. Utilisé" "totalUsed": "Esp. Utilisé"
}, },
"mealie": {
"recipes": "Recettes",
"users": "Utilisateurs",
"categories": "Catégories",
"tags": "Étiquettes"
},
"openmediavault": { "openmediavault": {
"downloading": "Téléchargement", "downloading": "Téléchargement",
"total": "Total", "total": "Total",
@@ -702,47 +739,23 @@
"passed": "Réussi", "passed": "Réussi",
"failed": "Échoué" "failed": "Échoué"
}, },
"mealie": {
"recipes": "Recettes",
"users": "Utilisateurs",
"categories": "Catégories",
"tags": "Étiquettes"
},
"atsumeru": {
"series": "Séries",
"archives": "Archives",
"chapters": "Chapitres",
"categories": "Catégories"
},
"calibreweb": {
"series": "Séries",
"books": "Ebooks",
"authors": "Auteurs",
"categories": "Catégories"
},
"uptimerobot": { "uptimerobot": {
"status": "Statut", "status": "Statut",
"uptime": "Disponibilité", "uptime": "Démarré depuis",
"lastDown": "Dernière interruption", "lastDown": "Dernière interruption",
"downDuration": "Durée d'interruption", "downDuration": "Durée d'interruption",
"sitesUp": "Sites en ligne", "sitesUp": "En ligne",
"sitesDown": "Sites hors ligne", "sitesDown": "Hors ligne",
"paused": "En pause", "paused": "En Pause",
"notyetchecked": "Non vérifié", "notyetchecked": "Non vérifié",
"up": "En ligne", "up": "Up",
"seemsdown": "Semble hors ligne", "seemsdown": "Semble hors ligne",
"down": "Hors ligne", "down": "Down",
"unknown": "Inconnu" "unknown": "Inconnu"
}, },
"opendtu": {
"relativePower": "Puissance %",
"yieldDay": "Aujourd'hui",
"limit": "Limite",
"absolutePower": "Puissance"
},
"calendar": { "calendar": {
"physicalRelease": "Release physique",
"inCinemas": "En salle", "inCinemas": "En salle",
"digitalRelease": "Release digitale" "physicalRelease": "Sortie physique",
"digitalRelease": "Sortie numérique"
} }
} }

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Greška", "error": "Greška",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Uspjelo", "passed": "Uspjelo",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Hiba", "error": "Hiba",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Megfelelt", "passed": "Megfelelt",

View File

@@ -610,7 +610,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Playing", "playing": "Playing",

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +1,21 @@
{ {
"navidrome": {
"nothing_streaming": "アクティブストリームなし",
"please_wait": "お待ちください"
},
"npm": {
"total": "合計",
"enabled": "有効",
"disabled": "無効"
},
"strelaysrv": {
"numActiveSessions": "セッション",
"numConnections": "コネクション",
"dataRelayed": "中継",
"transferRate": "レート"
},
"glances": {
"cpu": "CPU",
"wait": "お待ちください",
"temp": "温度",
"uptime": "UP",
"days": "日",
"hours": "時間",
"load": "ロード",
"warn": "警告",
"total": "トータル",
"free": "空き",
"used": "使用中",
"crit": "Crit",
"read": "読み込み",
"write": "書き込み",
"gpu": "GPU",
"mem": "メモリ",
"swap": "スワップ",
"_temp": "Temp"
},
"autobrr": {
"filters": "フィルター",
"indexers": "Indexers",
"approvedPushes": "承認済",
"rejectedPushes": "却下"
},
"gluetun": {
"region": "地域",
"country": "国",
"public_ip": "パブリックIP"
},
"common": { "common": {
"bytes": "{{value, bytes}}",
"bits": "{{value, bytes(bits: true)}}",
"bbytes": "{{value, bytes(binary: true)}}",
"bbits": "{{value, bytes(bits: true; binary: true)}}",
"byterate": "{{value, rate(bits: false)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}", "bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}" "bitrate": "{{value, rate(bits: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"percent": "{{value, percent}}",
"number": "{{value, number}}",
"ms": "{{value, number}}"
}, },
"widget": { "widget": {
"missing_type": "見つからないウィジェットタイプ: {{type}}",
"api_error": "APIエラー", "api_error": "APIエラー",
"information": "情報", "information": "情報",
"missing_type": "見つからないウィジェットタイプ: {{type}}",
"status": "状態", "status": "状態",
"url": "URL", "url": "URL",
"raw_error": "生のエラー", "raw_error": "生のエラー",
@@ -69,14 +32,14 @@
}, },
"resources": { "resources": {
"cpu": "CPU", "cpu": "CPU",
"mem": "MEM",
"total": "合計", "total": "合計",
"free": "Free", "free": "空き",
"used": "使用", "used": "使用",
"load": "ロード", "load": "ロード",
"mem": "MEM",
"temp": "温度", "temp": "温度",
"max": "Max", "max": "最大",
"uptime": "UP", "uptime": "上へ",
"months": "月", "months": "月",
"days": "日", "days": "日",
"hours": "時間", "hours": "時間",
@@ -88,14 +51,14 @@
"days": "日", "days": "日",
"wan": "WAN", "wan": "WAN",
"lan": "LAN", "lan": "LAN",
"wlan": "WLAN", "wlan": "Wi-Fi",
"devices": "デバイス", "devices": "デバイス",
"lan_devices": "LAN デバイス", "lan_devices": "LAN デバイス",
"wlan_devices": "WLAN デバイス", "wlan_devices": "WLAN デバイス",
"lan_users": "LAN ユーザ", "lan_users": "LAN ユーザ",
"wlan_users": "WLAN ユーザ", "wlan_users": "WLAN ユーザ",
"up": "UP", "up": "上へ",
"down": "DOWN", "down": "下へ",
"wait": "お待ちください", "wait": "お待ちください",
"empty_data": "サブシステム状態・不明" "empty_data": "サブシステム状態・不明"
}, },
@@ -104,20 +67,24 @@
"tx": "TX", "tx": "TX",
"mem": "MEM", "mem": "MEM",
"cpu": "CPU", "cpu": "CPU",
"running": "起動中",
"offline": "オフライン", "offline": "オフライン",
"error": "エラー", "error": "エラー",
"unknown": "不明", "unknown": "不明",
"running": "起動中", "healthy": "健全",
"starting": "起動中", "starting": "起動中",
"unhealthy": "非健全", "unhealthy": "非健全",
"not_found": "不明", "not_found": "不明",
"exited": "終了", "exited": "終了",
"partial": "部分的", "partial": "部分的"
"healthy": "健全"
}, },
"ping": { "ping": {
"http_status": "HTTP ステータス",
"error": "エラー", "error": "エラー",
"ping": "Ping" "ping": "Ping",
"down": "下へ",
"up": "上へ",
"not_available": "利用できません。"
}, },
"emby": { "emby": {
"playing": "再生中", "playing": "再生中",
@@ -129,21 +96,44 @@
"episodes": "エピソード", "episodes": "エピソード",
"songs": "曲" "songs": "曲"
}, },
"evcc": {
"pv_power": "発電量",
"battery_soc": "バッテリー",
"grid_power": "グリッド",
"home_power": "消費",
"charge_power": "チャージャー",
"watt_hour": "Wh"
},
"flood": { "flood": {
"download": "ダウンロード", "download": "ダウンロード",
"upload": "アップロード", "upload": "アップロード",
"leech": "リーチ", "leech": "リーチ",
"seed": "Seed" "seed": "シード"
},
"freshrss": {
"subscriptions": "購読",
"unread": "未読"
},
"caddy": {
"upstreams": "アップストリーム",
"requests": "現在のリクエスト",
"requests_failed": "失敗したリクエスト"
}, },
"changedetectionio": { "changedetectionio": {
"totalObserved": "全観測数", "totalObserved": "全観測数",
"diffsDetected": "変更数" "diffsDetected": "変更数"
}, },
"channelsdvrserver": {
"shows": "表示",
"recordings": "レコーディング",
"scheduled": "予定済",
"passes": "パス"
},
"tautulli": { "tautulli": {
"playing": "再生中", "playing": "再生中",
"transcoding": "変換中", "transcoding": "変換中",
"bitrate": "ビットレート", "bitrate": "ビットレート",
"no_active": "アクティブストリームし", "no_active": "アクティブストリームし",
"plex_connection_error": "Plex接続の確認" "plex_connection_error": "Plex接続の確認"
}, },
"omada": { "omada": {
@@ -160,9 +150,9 @@
}, },
"plex": { "plex": {
"streams": "アクティブストリーム", "streams": "アクティブストリーム",
"albums": "アルバム",
"movies": "映画", "movies": "映画",
"tv": "テレビ番組", "tv": "テレビ番組"
"albums": "アルバム"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "速度", "rate": "速度",
@@ -178,25 +168,33 @@
"download": "ダウンロード", "download": "ダウンロード",
"upload": "アップロード", "upload": "アップロード",
"leech": "リーチ", "leech": "リーチ",
"seed": "Seed" "seed": "シード"
}, },
"qbittorrent": { "qbittorrent": {
"download": "ダウンロード", "download": "ダウンロード",
"upload": "アップロード", "upload": "アップロード",
"leech": "Leech", "leech": "リーチ",
"seed": "Seed" "seed": "シード"
},
"qnap": {
"cpuUsage": "CPU使用量",
"memUsage": "MEM使用量",
"systemTempC": "システム温度",
"poolUsage": "プール使用量",
"volumeUsage": "ボリューム使用量",
"invalid": "無効"
}, },
"deluge": { "deluge": {
"download": "ダウンロード", "download": "ダウンロード",
"upload": "アップロード", "upload": "アップロード",
"leech": "Leech", "leech": "リーチ",
"seed": "Seed" "seed": "シード"
}, },
"downloadstation": { "downloadstation": {
"download": "ダウンロード", "download": "ダウンロード",
"upload": "アップロード", "upload": "アップロード",
"leech": "Leech", "leech": "リーチ",
"seed": "Seed" "seed": "シード"
}, },
"sonarr": { "sonarr": {
"wanted": "募集中", "wanted": "募集中",
@@ -208,14 +206,14 @@
"radarr": { "radarr": {
"wanted": "募集中", "wanted": "募集中",
"missing": "不明", "missing": "不明",
"queued": "キュー", "queued": "待機中",
"movies": "映画", "movies": "映画",
"queue": "キュー", "queue": "キュー",
"unknown": "Unknown" "unknown": "不明"
}, },
"lidarr": { "lidarr": {
"wanted": "募集中", "wanted": "募集中",
"queued": "キュー", "queued": "待機中",
"artists": "アーティスト" "artists": "アーティスト"
}, },
"readarr": { "readarr": {
@@ -225,7 +223,7 @@
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "欠番エピソード", "missingEpisodes": "欠番エピソード",
"missingMovies": "行方不明の映画" "missingMovies": "動画が見つかりません"
}, },
"ombi": { "ombi": {
"pending": "保留中", "pending": "保留中",
@@ -243,11 +241,17 @@
"approved": "承認済", "approved": "承認済",
"available": "利用可" "available": "利用可"
}, },
"pialert": {
"total": "合計",
"connected": "接続済み",
"new_devices": "新しいデバイス",
"down_alerts": "ダウンアラート"
},
"pihole": { "pihole": {
"queries": "クエリ", "queries": "クエリ",
"blocked": "ブロック中", "blocked": "ブロック中",
"gravity": "グラビティ", "blocked_percent": "ブロック %",
"blocked_percent": "ブロック %" "gravity": "グラビティ"
}, },
"adguard": { "adguard": {
"queries": "クエリ", "queries": "クエリ",
@@ -265,6 +269,20 @@
"stopped": "停止中", "stopped": "停止中",
"total": "合計" "total": "合計"
}, },
"tailscale": {
"address": "アドレス",
"expires": "失効",
"never": "なし",
"last_seen": "最終日時",
"now": "現在",
"years": "{{number}}年",
"weeks": "{{number}}月",
"days": "{{number}}日",
"hours": "{{number}}時間",
"minutes": "{{number}}分",
"seconds": "{{number}}秒",
"ago": "{{value}} 前"
},
"tdarr": { "tdarr": {
"queue": "キュー", "queue": "キュー",
"processed": "処理済み", "processed": "処理済み",
@@ -276,6 +294,15 @@
"services": "サービス", "services": "サービス",
"middleware": "ミドルウェア" "middleware": "ミドルウェア"
}, },
"navidrome": {
"nothing_streaming": "アクティブ・ストリーム無し",
"please_wait": "お待ちください"
},
"npm": {
"enabled": "有効",
"disabled": "無効",
"total": "合計"
},
"coinmarketcap": { "coinmarketcap": {
"configure": "1つ以上の暗号通貨を設定して追跡", "configure": "1つ以上の暗号通貨を設定して追跡",
"1hour": "1時間", "1hour": "1時間",
@@ -289,27 +316,45 @@
"messages": "メッセージ" "messages": "メッセージ"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "インデックス",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Grab",
"numberOfQueries": "クエリ", "numberOfQueries": "クエリ",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "失敗したグラブ",
"numberOfFailQueries": "失敗クエリー" "numberOfFailQueries": "失敗クエリー"
}, },
"jackett": { "jackett": {
"configured": "設定済", "configured": "設定済",
"errored": "エラー" "errored": "エラー"
}, },
"strelaysrv": {
"numActiveSessions": "セッション",
"numConnections": "コネクション",
"dataRelayed": "中継",
"transferRate": "速度"
},
"mastodon": { "mastodon": {
"user_count": "ユーザ", "user_count": "ユーザ",
"status_count": "ポスト", "status_count": "ポスト",
"domain_count": "ドメイン" "domain_count": "ドメイン"
}, },
"medusa": {
"wanted": "募集中",
"queued": "待機中",
"series": "シリーズ"
},
"minecraft": {
"players": "プレイヤー",
"version": "バージョン",
"status": "状態",
"up": "オンライン",
"down": "オフライン"
},
"miniflux": { "miniflux": {
"read": "既読", "read": "既読",
"unread": "未読" "unread": "未読"
}, },
"authentik": { "authentik": {
"users": "ユーザ", "users": "ユーザ",
"loginsLast24H": "ログイン (24時間)", "loginsLast24H": "ログイン (24時間)",
"failedLoginsLast24H": "ログイン失敗(24時間)" "failedLoginsLast24H": "ログイン失敗(24時間)"
}, },
@@ -319,6 +364,26 @@
"lxc": "LXC", "lxc": "LXC",
"vms": "VM" "vms": "VM"
}, },
"glances": {
"cpu": "CPU",
"load": "ロード",
"wait": "お待ちください",
"temp": "温度",
"_temp": "温度",
"warn": "警告",
"uptime": "上へ",
"total": "合計",
"free": "空き",
"used": "使用",
"days": "日",
"hours": "時間",
"crit": "クリティカル",
"read": "既読",
"write": "書き込み",
"gpu": "GPU",
"mem": "メモリ",
"swap": "スワップ"
},
"quicklaunch": { "quicklaunch": {
"bookmark": "ブックマーク", "bookmark": "ブックマーク",
"service": "サービス", "service": "サービス",
@@ -329,47 +394,47 @@
}, },
"wmo": { "wmo": {
"0-day": "晴れ", "0-day": "晴れ",
"1-day": "ほぼ晴れ",
"0-night": "晴れ", "0-night": "晴れ",
"1-night": "ほぼ晴れ", "1-day": "晴れ時々曇り",
"2-day": "一時くもり", "1-night": "晴れ時々曇り",
"2-night": "一部くもり", "2-day": "曇り時々晴れ",
"3-day": "くもり", "2-night": "曇り時々晴れ",
"3-night": "くもり", "3-day": "り",
"3-night": "曇り",
"45-day": "霧", "45-day": "霧",
"45-night": "霧", "45-night": "霧",
"48-day": "霧", "48-day": "霧",
"48-night": "霧", "48-night": "霧",
"51-day": "霧雨", "51-day": "霧雨",
"51-night": "霧雨", "51-night": "霧雨",
"53-day": "雨", "53-day": "雨",
"53-night": "雨", "53-night": "雨",
"55-day": "霧雨", "55-day": "霧雨",
"55-night": "霧雨", "55-night": "霧雨",
"56-day": "霧雨", "56-day": "着氷性の霧雨",
"56-night": "霧雨", "56-night": "着氷性の霧雨",
"57-day": "雨", "57-day": "着氷性の小雨",
"57-night": "雨", "57-night": "着氷性の小雨",
"61-day": "小雨", "61-day": "小雨",
"61-night": "小雨", "61-night": "小雨",
"63-day": "雨", "63-day": "雨",
"63-night": "雨", "63-night": "雨",
"67-night": "雨",
"71-day": "雪",
"65-day": "大雨", "65-day": "大雨",
"65-night": "大雨", "65-night": "大雨",
"66-day": "雨", "66-day": "着氷性の雨",
"66-night": "雨", "66-night": "着氷性の雨",
"67-day": "雨", "67-day": "着氷性の雨",
"71-night": "", "67-night": "着氷性の雨",
"71-day": "小雪",
"71-night": "小雪",
"73-day": "雪", "73-day": "雪",
"73-night": "雪", "73-night": "雪",
"75-day": "大雪", "75-day": "大雪",
"75-night": "大雪", "75-night": "大雪",
"77-day": "雪", "77-day": "雪",
"77-night": "雪", "77-night": "雪",
"80-day": "にわか雨", "80-day": "弱いにわか雨",
"80-night": "にわか雨", "80-night": "弱いにわか雨",
"81-day": "にわか雨", "81-day": "にわか雨",
"81-night": "にわか雨", "81-night": "にわか雨",
"82-day": "強いにわか雨", "82-day": "強いにわか雨",
@@ -390,17 +455,33 @@
"updates": "アップデート", "updates": "アップデート",
"update_available": "更新あり", "update_available": "更新あり",
"up_to_date": "最新", "up_to_date": "最新",
"child_bridges": "Child Bridges", "child_bridges": "子ブリッジ",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Up", "up": "上へ",
"pending": "Pending", "pending": "保留中",
"down": "Down" "down": "下へ"
},
"healthchecks": {
"new": "新着",
"up": "オンライン",
"grace": "猶予期間中",
"down": "オフライン",
"paused": "一時停止中",
"status": "状態",
"last_ping": "最後のPing",
"never": "Pingしていません"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "スキャン済", "containers_scanned": "スキャン済",
"containers_updated": "更新済", "containers_updated": "更新済",
"containers_failed": "失敗" "containers_failed": "失敗"
}, },
"autobrr": {
"approvedPushes": "承認済",
"rejectedPushes": "却下",
"filters": "フィルター",
"indexers": "インデックス"
},
"tubearchivist": { "tubearchivist": {
"downloads": "キュー", "downloads": "キュー",
"videos": "ビデオ", "videos": "ビデオ",
@@ -419,6 +500,11 @@
"queue": "キュー", "queue": "キュー",
"total": "合計" "total": "合計"
}, },
"gluetun": {
"public_ip": "パブリックIP",
"region": "地域",
"country": "国"
},
"hdhomerun": { "hdhomerun": {
"channels": "チャンネル", "channels": "チャンネル",
"hd": "HD" "hd": "HD"
@@ -429,7 +515,7 @@
"unknown": "不明" "unknown": "不明"
}, },
"paperlessngx": { "paperlessngx": {
"inbox": "受信", "inbox": "受信トレイ",
"total": "合計" "total": "合計"
}, },
"nextdns": { "nextdns": {
@@ -438,15 +524,21 @@
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU負荷", "cpuLoad": "CPU負荷",
"memoryUsed": "使用メモリ", "memoryUsed": "使用済みメモリ",
"uptime": "稼働時間", "uptime": "稼働時間",
"numberOfLeases": "リース" "numberOfLeases": "リース"
}, },
"xteve": { "xteve": {
"streams_all": "ストリーム", "streams_all": "すべてのストリーム",
"streams_active": "アクティブストリーム", "streams_active": "アクティブストリーム",
"streams_xepg": "XEPGチャンネル" "streams_xepg": "XEPGチャンネル"
}, },
"opendtu": {
"yieldDay": "今日",
"absolutePower": "電源",
"relativePower": "電源 %",
"limit": "リミット"
},
"opnsense": { "opnsense": {
"cpu": "CPU負荷", "cpu": "CPU負荷",
"memory": "アクティブ・メモリ", "memory": "アクティブ・メモリ",
@@ -459,21 +551,26 @@
"print_progress": "進捗状況", "print_progress": "進捗状況",
"layers": "レイヤー" "layers": "レイヤー"
}, },
"medusa": {
"wanted": "Wanted",
"queued": "Queued",
"series": "シリーズ"
},
"octoprint": { "octoprint": {
"temp_bed": "ベッド温度",
"printer_state": "状態", "printer_state": "状態",
"temp_tool": "ツール温度", "temp_tool": "ツール温度",
"temp_bed": "ベッド温度",
"job_completion": "完了" "job_completion": "完了"
}, },
"cloudflared": { "cloudflared": {
"origin_ip": "オリジンIP", "origin_ip": "オリジンIP",
"status": "状態" "status": "状態"
}, },
"pfsense": {
"load": "読み込み平均",
"memory": "メモリ使用量",
"wanStatus": "WANステータス",
"up": "上へ",
"down": "下へ",
"temp": "温度",
"disk": "ディスク使用量",
"wanIP": "WAN IP"
},
"proxmoxbackupserver": { "proxmoxbackupserver": {
"datastore_usage": "データストア", "datastore_usage": "データストア",
"failed_tasks_24h": "失敗タスク(24h)", "failed_tasks_24h": "失敗タスク(24h)",
@@ -490,18 +587,29 @@
"up": "サイトUp", "up": "サイトUp",
"down": "サイトDown", "down": "サイトDown",
"uptime": "稼働時間", "uptime": "稼働時間",
"incident": "Incident", "incident": "インシデント",
"m": "m" "m": ""
},
"atsumeru": {
"series": "シリーズ",
"archives": "アーカイブ",
"chapters": "チャプター",
"categories": "カテゴリー"
}, },
"komga": { "komga": {
"libraries": "ライブラリ", "libraries": "ライブラリ",
"series": "シリーズ", "series": "シリーズ",
"books": "書籍" "books": "書籍"
}, },
"diskstation": {
"days": "日",
"uptime": "稼働時間",
"volumeAvailable": "利用可"
},
"mylar": { "mylar": {
"series": "シリーズ", "series": "シリーズ",
"issues": "課題", "issues": "課題",
"wanted": "Wanted" "wanted": "募集中"
}, },
"photoprism": { "photoprism": {
"albums": "アルバム", "albums": "アルバム",
@@ -509,11 +617,6 @@
"videos": "ビデオ", "videos": "ビデオ",
"people": "人" "people": "人"
}, },
"diskstation": {
"days": "日",
"uptime": "稼働時間",
"volumeAvailable": "利用可能"
},
"fileflows": { "fileflows": {
"queue": "キュー", "queue": "キュー",
"processing": "処理中", "processing": "処理中",
@@ -537,8 +640,8 @@
"kopia": { "kopia": {
"status": "状態", "status": "状態",
"size": "サイズ", "size": "サイズ",
"lastrun": "最終実行", "lastrun": "前回の実行",
"nextrun": "次の実行", "nextrun": "次の実行",
"failed": "失敗" "failed": "失敗"
}, },
"unmanic": { "unmanic": {
@@ -546,16 +649,6 @@
"total_workers": "トータル・ワーカー", "total_workers": "トータル・ワーカー",
"records_total": "キューの長さ" "records_total": "キューの長さ"
}, },
"healthchecks": {
"never": "Pingしていません",
"new": "New",
"up": "オンライン",
"grace": "猶予期間中",
"down": "オフライン",
"paused": "一時停止中",
"status": "状態",
"last_ping": "最後のPing"
},
"pterodactyl": { "pterodactyl": {
"servers": "サーバ", "servers": "サーバ",
"nodes": "ノード" "nodes": "ノード"
@@ -565,17 +658,10 @@
"targets_down": "ターゲット Down", "targets_down": "ターゲット Down",
"targets_total": "ターゲット合計" "targets_total": "ターゲット合計"
}, },
"minecraft": {
"players": "プレイヤー",
"version": "バージョン",
"status": "状態",
"up": "オンライン",
"down": "オフライン"
},
"ghostfolio": { "ghostfolio": {
"gross_percent_max": "全期間",
"gross_percent_today": "今日", "gross_percent_today": "今日",
"gross_percent_1y": "1年" "gross_percent_1y": "1年",
"gross_percent_max": "全期間"
}, },
"audiobookshelf": { "audiobookshelf": {
"podcasts": "ポッドキャスト", "podcasts": "ポッドキャスト",
@@ -588,161 +674,88 @@
"lights_on": "点灯", "lights_on": "点灯",
"switches_on": "スイッチオン" "switches_on": "スイッチオン"
}, },
"freshrss": {
"subscriptions": "購読",
"unread": "未読"
},
"channelsdvrserver": {
"shows": "ショー",
"recordings": "レコーディング",
"scheduled": "予定済",
"passes": "パス"
},
"whatsupdocker": { "whatsupdocker": {
"monitoring": "モニタリング", "monitoring": "モニタリング",
"updates": "アップデート" "updates": "アップデート"
}, },
"tailscale": {
"address": "アドレス",
"expires": "失効",
"never": "なし",
"last_seen": "最終日時",
"now": "現在",
"years": "{{number}}年",
"weeks": "{{number}}月",
"days": "{{number}}日",
"hours": "{{number}}時間",
"minutes": "{{number}}分",
"seconds": "{{number}}秒",
"ago": "{{value}} 前"
},
"qnap": {
"cpuUsage": "CPU使用量",
"memUsage": "MEM使用量",
"systemTempC": "システム温度",
"poolUsage": "プール使用量",
"volumeUsage": "ボリューム使用量",
"invalid": "無効"
},
"pfsense": {
"up": "アップ",
"load": "読み込み平均",
"memory": "メモリ使用量",
"wanStatus": "WANステータス",
"down": "ダウン",
"temp": "温度",
"disk": "ディスク使用量",
"wanIP": "WAN IP"
},
"caddy": {
"upstreams": "アップストリーム",
"requests": "現在のリクエスト",
"requests_failed": "失敗したリクエスト"
},
"evcc": {
"watt_hour": "Wh",
"pv_power": "発電量",
"battery_soc": "バッテリー",
"grid_power": "グリッド",
"home_power": "消費",
"charge_power": "チャージャー"
},
"pialert": {
"total": "トータル",
"connected": "接続済み",
"new_devices": "新しいデバイス",
"down_alerts": "ダウンアラート"
},
"jdownloader": {
"downloadCount": "キュー",
"downloadSpeed": "スピード",
"downloadBytesRemaining": "残り",
"downloadTotalBytes": "サイズ"
},
"kavita": {
"seriesCount": "シリーズ",
"totalFiles": "ファイル"
},
"gamedig": {
"name": "名前",
"map": "マップ",
"currentPlayers": "現在のプレーヤー",
"players": "プレーヤー",
"maxPlayers": "最大プレーヤー",
"bots": "ボット",
"ping": "Ping",
"status": "ステータス",
"online": "オンライン",
"offline": "オフライン"
},
"azuredevops": {
"result": "結果",
"status": "ステータス",
"buildId": "ビルドID",
"succeeded": "成功",
"notStarted": "Not Started",
"failed": "失敗",
"canceled": "キャンセル",
"inProgress": "進行中",
"totalPrs": "合計PR数",
"myPrs": "私のPR",
"approved": "承認"
},
"urbackup": {
"ok": "Ok",
"errored": "エラー",
"noRecent": "期限切れ",
"totalUsed": "使用済みストレージ"
},
"openmediavault": {
"downloading": "ダウンロード中",
"total": "トータル",
"running": "実行中",
"stopped": "停止中",
"passed": "合格",
"failed": "不合格"
},
"mealie": {
"recipes": "レシピ",
"users": "ユーザー",
"categories": "カテゴリー",
"tags": "タグ"
},
"atsumeru": {
"series": "シリーズ",
"archives": "アーカイブ",
"chapters": "チャプター",
"categories": "カテゴリー"
},
"calibreweb": { "calibreweb": {
"books": "書籍", "books": "書籍",
"authors": "著者", "authors": "著者",
"categories": "カテゴリー", "categories": "カテゴリー",
"series": "シリーズ" "series": "シリーズ"
}, },
"uptimerobot": { "jdownloader": {
"status": "Status", "downloadCount": "キュー",
"uptime": "Uptime", "downloadBytesRemaining": "残り",
"lastDown": "Last Downtime", "downloadTotalBytes": "サイズ",
"downDuration": "Downtime Duration", "downloadSpeed": "スピード"
"sitesUp": "Sites Up",
"sitesDown": "Sites Down",
"paused": "Paused",
"notyetchecked": "Not Yet Checked",
"up": "Up",
"seemsdown": "Seems Down",
"down": "Down",
"unknown": "Unknown"
}, },
"opendtu": { "kavita": {
"relativePower": "Power %", "seriesCount": "シリーズ",
"yieldDay": "Today", "totalFiles": "ファイル"
"limit": "Limit", },
"absolutePower": "Power" "azuredevops": {
"result": "結果",
"status": "状態",
"buildId": "ビルドID",
"succeeded": "成功",
"notStarted": "開始していません",
"failed": "失敗",
"canceled": "キャンセル",
"inProgress": "進行中",
"totalPrs": "合計PR数",
"myPrs": "私のPR",
"approved": "承認済"
},
"gamedig": {
"status": "状態",
"online": "オンライン",
"offline": "オフライン",
"name": "名前",
"map": "マップ",
"currentPlayers": "現在のプレーヤー",
"players": "プレイヤー",
"maxPlayers": "最大プレイヤー数",
"bots": "ボット",
"ping": "Ping"
},
"urbackup": {
"ok": "はい",
"errored": "エラー",
"noRecent": "期限切れ",
"totalUsed": "使用済みストレージ"
},
"mealie": {
"recipes": "レシピ",
"users": "ユーザ",
"categories": "カテゴリー",
"tags": "タグ"
},
"openmediavault": {
"downloading": "ダウンロード中",
"total": "合計",
"running": "起動中",
"stopped": "停止中",
"passed": "合格",
"failed": "失敗"
},
"uptimerobot": {
"status": "状態",
"uptime": "稼働時間",
"lastDown": "最後のダウンタイム",
"downDuration": "ダウンタイム感覚",
"sitesUp": "サイトUp",
"sitesDown": "サイトDown",
"paused": "一時停止中",
"notyetchecked": "チェックされていません",
"up": "上へ",
"seemsdown": "ダウンしているようです",
"down": "下へ",
"unknown": "不明"
}, },
"calendar": { "calendar": {
"physicalRelease": "Physical release", "inCinemas": "映画館内",
"inCinemas": "In cinemas", "physicalRelease": "物理的なリリース",
"digitalRelease": "Digital release" "digitalRelease": "デジタル・リリース"
} }
} }

View File

@@ -85,7 +85,9 @@
}, },
"ping": { "ping": {
"error": "오류", "error": "오류",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "재생 중", "playing": "재생 중",

View File

@@ -71,7 +71,9 @@
}, },
"ping": { "ping": {
"error": "Kļūda", "error": "Kļūda",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Atskaņo", "playing": "Atskaņo",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Ralat", "error": "Ralat",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Lulus", "passed": "Lulus",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,42 @@
{ {
"common": {
"bytes": "{{value, bytes}}",
"bits": "{{value, bytes(bits: true)}}",
"bbytes": "{{value, bytes(binary: true)}}",
"bbits": "{{value, bytes(bits: true; binary: true)}}",
"byterate": "{{value, rate(bits: false)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bitrate": "{{value, rate(bits: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"percent": "{{value, percent}}",
"number": "{{value, number}}",
"ms": "{{value, number}}"
},
"widget": {
"missing_type": "Brakujący typ widżetu: {{type}}",
"api_error": "Błąd API",
"information": "Informacje",
"status": "Stan",
"url": "Adres URL",
"raw_error": "Niesformatowany błąd",
"response_data": "Dane odpowiedzi"
},
"weather": { "weather": {
"current": "Aktualna lokalizacja",
"allow": "Kliknij, aby zezwolić", "allow": "Kliknij, aby zezwolić",
"updating": "Aktualizacja", "updating": "Aktualizacja",
"wait": "Proszę czekać", "wait": "Proszę czekać"
"current": "Aktualna lokalizacja"
}, },
"search": { "search": {
"placeholder": "Szukaj…" "placeholder": "Szukaj…"
}, },
"resources": { "resources": {
"used": "Użyte", "cpu": "Procesor",
"load": "Obciążenie", "mem": "PAM",
"total": "Całkowite", "total": "Całkowite",
"free": "Wolne", "free": "Wolne",
"cpu": "CPU", "used": "Użyte",
"mem": "PAM", "load": "Obciążenie",
"temp": "TEMP.", "temp": "TEMP.",
"max": "Maks", "max": "Maks",
"uptime": "CZAS", "uptime": "CZAS",
@@ -23,16 +45,90 @@
"hours": "godz", "hours": "godz",
"minutes": "min" "minutes": "min"
}, },
"unifi": {
"users": "Użytkownicy",
"uptime": "Czas pracy systemu",
"days": "Dni",
"wan": "Sieć WAN",
"lan": "Sieć LAN",
"wlan": "Sieć WLAN",
"devices": "Urządzenia",
"lan_devices": "Urządzenia LAN",
"wlan_devices": "Urządzenia WLAN",
"lan_users": "Użytkownicy LAN",
"wlan_users": "Użytkownicy WLAN",
"up": "CZAS",
"down": "Pobieranie",
"wait": "Proszę czekać",
"empty_data": "Nieznany stan"
},
"docker": {
"rx": "Rx",
"tx": "Tx",
"mem": "PAM",
"cpu": "Procesor",
"running": "Działa",
"offline": "Offline",
"error": "Błąd",
"unknown": "Nieznany",
"healthy": "Zdrowy",
"starting": "Rozpoczynanie",
"unhealthy": "Niezdrowe",
"not_found": "Nie znaleziono",
"exited": "Zakończone",
"partial": "Częściowe"
},
"ping": {
"http_status": "HTTP status",
"error": "Błąd",
"ping": "Ping",
"down": "Down",
"up": "Up",
"not_available": "Not Available"
},
"emby": { "emby": {
"no_active": "Brak aktywnych strumieni",
"playing": "Odtwarzanie", "playing": "Odtwarzanie",
"transcoding": "Transkodowanie", "transcoding": "Transkodowanie",
"bitrate": "Bitrate", "bitrate": "Bitrate",
"no_active": "Brak aktywnych strumieni",
"movies": "Filmy", "movies": "Filmy",
"series": "Seriale", "series": "Seriale",
"episodes": "Odcinki", "episodes": "Odcinki",
"songs": "Piosenki" "songs": "Piosenki"
}, },
"evcc": {
"pv_power": "Production",
"battery_soc": "Battery",
"grid_power": "Siatka",
"home_power": "Consumption",
"charge_power": "Charger",
"watt_hour": "Wh"
},
"flood": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"freshrss": {
"subscriptions": "Subskrypcje",
"unread": "Nieprzeczytane"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Current requests",
"requests_failed": "Failed requests"
},
"changedetectionio": {
"totalObserved": "Obserwowanych ogółem",
"diffsDetected": "Wykryto różnic"
},
"channelsdvrserver": {
"shows": "Shows",
"recordings": "Nagrywanie",
"scheduled": "W kolejce",
"passes": "Passes"
},
"tautulli": { "tautulli": {
"playing": "Odtwarzanie", "playing": "Odtwarzanie",
"transcoding": "Transkodowanie", "transcoding": "Transkodowanie",
@@ -40,58 +136,24 @@
"no_active": "Brak aktywnych strumieni", "no_active": "Brak aktywnych strumieni",
"plex_connection_error": "Check Plex Connection" "plex_connection_error": "Check Plex Connection"
}, },
"speedtest": { "omada": {
"download": "Pobieranie", "connectedAp": "Połączone punkty dostępowe",
"ping": "Ping", "activeUser": "Aktywne urządzenia",
"upload": "Wysyłanie" "alerts": "Alarmy",
}, "connectedGateway": "Połączone bramy",
"portainer": { "connectedSwitches": "Połączone przełączniki"
"running": "Działające",
"stopped": "Zatrzymane",
"total": "Ogólnie"
},
"coinmarketcap": {
"1day": "1 dzień",
"7days": "7 dni",
"30days": "30 dni",
"1hour": "1 godzina",
"configure": "Wybierz jedną lub więcej kryptowalut do śledzenia"
},
"gotify": {
"apps": "Aplikacje",
"clients": "Klienci",
"messages": "Wiadomości"
},
"widget": {
"missing_type": "Brakujący typ widżetu: {{type}}",
"api_error": "Błąd API",
"status": "Stan",
"url": "Adres URL",
"information": "Informacje",
"raw_error": "Niesformatowany błąd",
"response_data": "Dane odpowiedzi"
},
"docker": {
"rx": "Rx",
"tx": "Tx",
"mem": "Pamięć",
"cpu": "Procesor",
"offline": "Offline",
"error": "Błąd",
"unknown": "Nieznany",
"running": "Działa",
"starting": "Rozpoczynanie",
"unhealthy": "Niezdrowe",
"not_found": "Nie znaleziono",
"exited": "Exited",
"partial": "Częściowe",
"healthy": "Zdrowy"
}, },
"nzbget": { "nzbget": {
"rate": "Szybkość", "rate": "Szybkość",
"remaining": "Pozostało", "remaining": "Pozostało",
"downloaded": "Pobrano" "downloaded": "Pobrano"
}, },
"plex": {
"streams": "Aktywne strumienie",
"albums": "Albumy",
"movies": "Filmy",
"tv": "Seriale"
},
"sabnzbd": { "sabnzbd": {
"rate": "Szybkość", "rate": "Szybkość",
"queue": "Kolejka", "queue": "Kolejka",
@@ -108,20 +170,46 @@
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"qbittorrent": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"qnap": {
"cpuUsage": "CPU Usage",
"memUsage": "MEM Usage",
"systemTempC": "System Temp",
"poolUsage": "Pool Usage",
"volumeUsage": "Volume Usage",
"invalid": "Invalid"
},
"deluge": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"downloadstation": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"sonarr": { "sonarr": {
"wanted": "Poszukiwane", "wanted": "Poszukiwane",
"queued": "W kolejce", "queued": "W kolejce",
"series": "Seriale", "series": "Seriale",
"queue": "Queue", "queue": "Kolejka",
"unknown": "Unknown" "unknown": "Nieznany"
}, },
"radarr": { "radarr": {
"wanted": "Poszukiwane", "wanted": "Poszukiwane",
"missing": "Brakujące",
"queued": "W kolejce", "queued": "W kolejce",
"movies": "Filmy", "movies": "Filmy",
"missing": "Brakujące", "queue": "Kolejka",
"queue": "Queue", "unknown": "Nieznany"
"unknown": "Unknown"
}, },
"lidarr": { "lidarr": {
"wanted": "Poszukiwane", "wanted": "Poszukiwane",
@@ -149,25 +237,83 @@
}, },
"overseerr": { "overseerr": {
"pending": "Oczekiwane", "pending": "Oczekiwane",
"processing": "Przetwarzane",
"approved": "Zaakceptowane", "approved": "Zaakceptowane",
"available": "Dostępne", "available": "Dostępne"
"processing": "Przetwarzane" },
"pialert": {
"total": "Całkowite",
"connected": "Connected",
"new_devices": "New Devices",
"down_alerts": "Down Alerts"
}, },
"pihole": { "pihole": {
"queries": "Zapytania", "queries": "Zapytania",
"blocked": "Zablokowane", "blocked": "Zablokowane",
"gravity": "Grawitacja", "blocked_percent": "Blocked %",
"blocked_percent": "Blocked %" "gravity": "Grawitacja"
},
"adguard": {
"queries": "Zapytania",
"blocked": "Zablokowane",
"filtered": "Przefiltrowane",
"latency": "Opóźnienia"
},
"speedtest": {
"upload": "Wysyłanie",
"download": "Pobieranie",
"ping": "Ping"
},
"portainer": {
"running": "Działa",
"stopped": "Zatrzymane",
"total": "Całkowite"
},
"tailscale": {
"address": "Address",
"expires": "Expires",
"never": "Nigdy",
"last_seen": "Last Seen",
"now": "Teraz",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "{{value}} Ago"
},
"tdarr": {
"queue": "Kolejka",
"processed": "Przetworzone",
"errored": "Błędne",
"saved": "Zapisane"
}, },
"traefik": { "traefik": {
"routers": "Routery", "routers": "Routery",
"services": "Serwisy", "services": "Serwisy",
"middleware": "Pośrednicy" "middleware": "Pośrednicy"
}, },
"navidrome": {
"nothing_streaming": "Brak aktywnych strumieni",
"please_wait": "Proszę czekać"
},
"npm": { "npm": {
"enabled": "Włączone", "enabled": "Włączone",
"disabled": "Wyłączone", "disabled": "Wyłączone",
"total": "Ogólnie" "total": "Całkowite"
},
"coinmarketcap": {
"configure": "Wybierz jedną lub więcej kryptowalut do śledzenia",
"1hour": "1 godzina",
"1day": "1 dzień",
"7days": "7 dni",
"30days": "30 dni"
},
"gotify": {
"apps": "Aplikacje",
"clients": "Klienci",
"messages": "Wiadomości"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indeksery", "enableIndexers": "Indeksery",
@@ -180,28 +326,32 @@
"configured": "Skonfigurowane", "configured": "Skonfigurowane",
"errored": "Błędne" "errored": "Błędne"
}, },
"adguard": { "strelaysrv": {
"queries": "Zapytania", "numActiveSessions": "Sesje",
"blocked": "Zablokowane", "numConnections": "Połączenia",
"filtered": "Przefiltrowane", "dataRelayed": "Przekazane",
"latency": "Opóźnienia" "transferRate": "Szybkość"
},
"qbittorrent": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
}, },
"mastodon": { "mastodon": {
"user_count": "Użytkownicy", "user_count": "Użytkownicy",
"status_count": "Posty", "status_count": "Posty",
"domain_count": "Domeny" "domain_count": "Domeny"
}, },
"strelaysrv": { "medusa": {
"numActiveSessions": "Sesje", "wanted": "Poszukiwane",
"numConnections": "Połączenia", "queued": "W kolejce",
"dataRelayed": "Przekazane", "series": "Seriale"
"transferRate": "Przesył" },
"minecraft": {
"players": "Gracze",
"version": "Wersja",
"status": "Stan",
"up": "Online",
"down": "Offline"
},
"miniflux": {
"read": "Przeczytane",
"unread": "Nieprzeczytane"
}, },
"authentik": { "authentik": {
"users": "Użytkownicy", "users": "Użytkownicy",
@@ -209,60 +359,40 @@
"failedLoginsLast24H": "Nieudane logowania (24h)" "failedLoginsLast24H": "Nieudane logowania (24h)"
}, },
"proxmox": { "proxmox": {
"mem": "Pamięć", "mem": "PAM",
"cpu": "Procesor", "cpu": "Procesor",
"lxc": "Kontenery LXC", "lxc": "Kontenery LXC",
"vms": "Maszyn wirtualnych" "vms": "Maszyn wirtualnych"
}, },
"unifi": {
"users": "Użytkownicy",
"uptime": "Czas pracy systemu",
"days": "Dni",
"wan": "WAN",
"lan_users": "Użytkownicy LAN",
"wlan_users": "Użytkownicy WLAN",
"up": "Wysyłanie",
"down": "Pobieranie",
"wait": "Proszę czekać",
"lan": "LAN",
"wlan": "WLAN",
"devices": "Urządzenia",
"lan_devices": "Urządzenia LAN",
"wlan_devices": "Urządzenia WLAN",
"empty_data": "Nieznany stan"
},
"plex": {
"streams": "Aktywne strumienie",
"movies": "Filmy",
"tv": "Seriale",
"albums": "Albumy"
},
"glances": { "glances": {
"cpu": "Procesor", "cpu": "Procesor",
"load": "Obciążenie",
"wait": "Proszę czekać", "wait": "Proszę czekać",
"temp": "TEMP", "temp": "TEMP.",
"_temp": "Temperatura",
"warn": "Ostrzeżenie",
"uptime": "CZAS", "uptime": "CZAS",
"total": "Całkowite",
"free": "Wolne",
"used": "Użyte",
"days": "dni", "days": "dni",
"hours": "godz", "hours": "godz",
"load": "Load",
"warn": "Warn",
"total": "Total",
"free": "Free",
"used": "Used",
"crit": "Crit", "crit": "Crit",
"read": "Read", "read": "Przeczytane",
"write": "Write", "write": "Zapis",
"gpu": "GPU", "gpu": "Karta graficzna",
"mem": "Mem", "mem": "Pamięć",
"swap": "Swap", "swap": "Swap"
"_temp": "Temp"
}, },
"changedetectionio": { "quicklaunch": {
"diffsDetected": "Wykryto różnic", "bookmark": "Zakładka",
"totalObserved": "Obserwowanych ogółem" "service": "Usługi",
"search": "Wyszukaj",
"custom": "Niestandardowe",
"visit": "Odwiedź",
"url": "Adres URL"
}, },
"wmo": { "wmo": {
"77-day": "Ziarnisty śnieg",
"0-day": "Słoneczny", "0-day": "Słoneczny",
"0-night": "Bezchmurny", "0-night": "Bezchmurny",
"1-day": "Głównie słoneczny", "1-day": "Głównie słoneczny",
@@ -301,6 +431,7 @@
"73-night": "Śnieg", "73-night": "Śnieg",
"75-day": "Ciężki śnieg", "75-day": "Ciężki śnieg",
"75-night": "Ciężki śnieg", "75-night": "Ciężki śnieg",
"77-day": "Ziarnisty śnieg",
"77-night": "Ziarnisty śnieg", "77-night": "Ziarnisty śnieg",
"80-day": "Lekkie opady", "80-day": "Lekkie opady",
"80-night": "Lekkie opady", "80-night": "Lekkie opady",
@@ -319,14 +450,6 @@
"99-day": "Burza z gradobiciem", "99-day": "Burza z gradobiciem",
"99-night": "Burza z gradobiciem" "99-night": "Burza z gradobiciem"
}, },
"quicklaunch": {
"bookmark": "Zakładka",
"service": "Usługi",
"search": "Wyszukaj",
"custom": "Niestandardowe",
"visit": "Odwiedź",
"url": "Adres URL"
},
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
"updates": "Aktualizacje", "updates": "Aktualizacje",
@@ -335,20 +458,30 @@
"child_bridges": "Child Bridges", "child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"up": "Up", "up": "Up",
"pending": "Oczekujące", "pending": "Oczekiwane",
"down": "Down" "down": "Down"
}, },
"healthchecks": {
"new": "Nowy",
"up": "Online",
"grace": "In Grace Period",
"down": "Offline",
"paused": "Zatrzymane",
"status": "Stan",
"last_ping": "Last Ping",
"never": "No pings yet"
},
"watchtower": {
"containers_scanned": "Zeskanowane",
"containers_updated": "Zaktualizowane",
"containers_failed": "Niepowodzenie"
},
"autobrr": { "autobrr": {
"approvedPushes": "Zaakceptowane", "approvedPushes": "Zaakceptowane",
"rejectedPushes": "Odrzucone", "rejectedPushes": "Odrzucone",
"filters": "Filtry", "filters": "Filtry",
"indexers": "Indeksery" "indexers": "Indeksery"
}, },
"watchtower": {
"containers_scanned": "Zeskanowane",
"containers_updated": "Zaktualizowane",
"containers_failed": "Niepowodzenie"
},
"tubearchivist": { "tubearchivist": {
"downloads": "Kolejka", "downloads": "Kolejka",
"videos": "Pliki wideo", "videos": "Pliki wideo",
@@ -358,18 +491,14 @@
"truenas": { "truenas": {
"load": "Obciążenie systemu", "load": "Obciążenie systemu",
"uptime": "Czas działania", "uptime": "Czas działania",
"alerts": "Ostrzeżenia", "alerts": "Alarmy",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"navidrome": {
"please_wait": "Proszę czekać",
"nothing_streaming": "Brak aktywnych strumieni"
},
"pyload": { "pyload": {
"speed": "Prędkość", "speed": "Prędkość",
"active": "Aktywne", "active": "Aktywny",
"queue": "Kolejka", "queue": "Kolejka",
"total": "Razem" "total": "Całkowite"
}, },
"gluetun": { "gluetun": {
"public_ip": "Adres publiczny", "public_ip": "Adres publiczny",
@@ -380,62 +509,19 @@
"channels": "Kanały", "channels": "Kanały",
"hd": "HD" "hd": "HD"
}, },
"ping": {
"error": "Błąd",
"ping": "Ping"
},
"scrutiny": { "scrutiny": {
"passed": "Powodzenie", "passed": "Powodzenie",
"failed": "Nieudane", "failed": "Niepowodzenie",
"unknown": "Nieznane" "unknown": "Nieznany"
}, },
"paperlessngx": { "paperlessngx": {
"inbox": "Skrzynka odbiorcza", "inbox": "Skrzynka odbiorcza",
"total": "W sumie" "total": "Całkowite"
},
"deluge": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"flood": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"tdarr": {
"queue": "Kolejka",
"processed": "Przetworzone",
"errored": "Błędne",
"saved": "Zapisane"
},
"miniflux": {
"read": "Przeczytane",
"unread": "Nieprzeczytane"
}, },
"nextdns": { "nextdns": {
"wait": "Proszę czekać", "wait": "Proszę czekać",
"no_devices": "Nie otrzymano danych urządzenia" "no_devices": "Nie otrzymano danych urządzenia"
}, },
"common": {
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
},
"omada": {
"connectedSwitches": "Połączone przełączniki",
"connectedAp": "Połączone punkty dostępowe",
"activeUser": "Aktywne urządzenia",
"alerts": "Alarmy",
"connectedGateway": "Połączone bramy"
},
"downloadstation": {
"download": "Pobieranie",
"upload": "Wysyłanie",
"leech": "Leech",
"seed": "Seed"
},
"mikrotik": { "mikrotik": {
"cpuLoad": "Obciążenie procesora", "cpuLoad": "Obciążenie procesora",
"memoryUsed": "Zuyżyta pamięć", "memoryUsed": "Zuyżyta pamięć",
@@ -447,6 +533,12 @@
"streams_active": "Aktywne strumienie", "streams_active": "Aktywne strumienie",
"streams_xepg": "Kanały XEPG" "streams_xepg": "Kanały XEPG"
}, },
"opendtu": {
"yieldDay": "Dzisiaj",
"absolutePower": "Power",
"relativePower": "Power %",
"limit": "Limit"
},
"opnsense": { "opnsense": {
"cpu": "Obciążenie procesora", "cpu": "Obciążenie procesora",
"memory": "Pamięć rzeczywista", "memory": "Pamięć rzeczywista",
@@ -459,31 +551,36 @@
"print_progress": "Postęp", "print_progress": "Postęp",
"layers": "Warstwy" "layers": "Warstwy"
}, },
"medusa": {
"wanted": "Poszukiwane",
"queued": "Zakolejkowane",
"series": "Seriale"
},
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "Stan",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Ukończono" "job_completion": "Ukończono"
}, },
"cloudflared": { "cloudflared": {
"origin_ip": "Origin IP", "origin_ip": "Origin IP",
"status": "Status" "status": "Stan"
},
"pfsense": {
"load": "Load Avg",
"memory": "Mem Usage",
"wanStatus": "WAN Status",
"up": "Up",
"down": "Down",
"temp": "Temperatura",
"disk": "Disk Usage",
"wanIP": "WAN IP"
}, },
"proxmoxbackupserver": { "proxmoxbackupserver": {
"datastore_usage": "Datastore", "datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h", "failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU", "cpu_usage": "Procesor",
"memory_usage": "Pamięć" "memory_usage": "Pamięć"
}, },
"immich": { "immich": {
"users": "Użytkownicy", "users": "Użytkownicy",
"photos": "Zdjęcia", "photos": "Zdjęcia",
"videos": "Filmy", "videos": "Pliki wideo",
"storage": "Pamięć" "storage": "Pamięć"
}, },
"uptimekuma": { "uptimekuma": {
@@ -493,31 +590,37 @@
"incident": "Incydent", "incident": "Incydent",
"m": "min" "m": "min"
}, },
"atsumeru": {
"series": "Seriale",
"archives": "Archives",
"chapters": "Chapters",
"categories": "Categories"
},
"komga": { "komga": {
"libraries": "Biblioteki", "libraries": "Biblioteki",
"series": "Seriale", "series": "Seriale",
"books": "Książki" "books": "Książki"
}, },
"diskstation": {
"days": "Dni",
"uptime": "Czas działania",
"volumeAvailable": "Dostępne"
},
"mylar": { "mylar": {
"series": "Seriale", "series": "Seriale",
"issues": "Zgłoszenia", "issues": "Zgłoszenia",
"wanted": "Wanted" "wanted": "Poszukiwane"
}, },
"photoprism": { "photoprism": {
"albums": "Albumy", "albums": "Albumy",
"photos": "Zdjęcia", "photos": "Zdjęcia",
"videos": "Filmy", "videos": "Pliki wideo",
"people": "Ludzie" "people": "Ludzie"
}, },
"diskstation": {
"uptime": "Czas działania",
"volumeAvailable": "Dostępne",
"days": "Dni"
},
"fileflows": { "fileflows": {
"queue": "Kolejka", "queue": "Kolejka",
"processing": "Przetwarzanie", "processing": "Przetwarzane",
"processed": "Processed", "processed": "Przetworzone",
"time": "Czas" "time": "Czas"
}, },
"grafana": { "grafana": {
@@ -535,27 +638,17 @@
"numshares": "Shared Items" "numshares": "Shared Items"
}, },
"kopia": { "kopia": {
"status": "Status", "status": "Stan",
"size": "Rozmiar", "size": "Rozmiar",
"lastrun": "Ostatnie uruchomienie", "lastrun": "Ostatnie uruchomienie",
"nextrun": "Next Run", "nextrun": "Next Run",
"failed": "Nieudane" "failed": "Niepowodzenie"
}, },
"unmanic": { "unmanic": {
"active_workers": "Aktywni pracownicy", "active_workers": "Aktywni pracownicy",
"total_workers": "Total Workers", "total_workers": "Total Workers",
"records_total": "Długość kolejki" "records_total": "Długość kolejki"
}, },
"healthchecks": {
"new": "Nowy",
"up": "Online",
"grace": "In Grace Period",
"down": "Offline",
"paused": "Zatrzymane",
"status": "Status",
"last_ping": "Last Ping",
"never": "No pings yet"
},
"pterodactyl": { "pterodactyl": {
"servers": "Serwery", "servers": "Serwery",
"nodes": "Nodes" "nodes": "Nodes"
@@ -565,13 +658,6 @@
"targets_down": "Targets Down", "targets_down": "Targets Down",
"targets_total": "Total Targets" "targets_total": "Total Targets"
}, },
"minecraft": {
"players": "Gracze",
"version": "Wersja",
"status": "Status",
"up": "Online",
"down": "Offline"
},
"ghostfolio": { "ghostfolio": {
"gross_percent_today": "Dzisiaj", "gross_percent_today": "Dzisiaj",
"gross_percent_1y": "Rok", "gross_percent_1y": "Rok",
@@ -588,105 +674,50 @@
"lights_on": "Lights On", "lights_on": "Lights On",
"switches_on": "Switches On" "switches_on": "Switches On"
}, },
"freshrss": {
"subscriptions": "Subskrypcje",
"unread": "Nieprzeczytane"
},
"channelsdvrserver": {
"shows": "Shows",
"recordings": "Nagrywanie",
"scheduled": "W kolejce",
"passes": "Passes"
},
"whatsupdocker": { "whatsupdocker": {
"monitoring": "Monitoring", "monitoring": "Monitoring",
"updates": "Aktualizacje" "updates": "Aktualizacje"
}, },
"tailscale": { "calibreweb": {
"address": "Address", "books": "Książki",
"expires": "Expires", "authors": "Authors",
"never": "Never", "categories": "Categories",
"last_seen": "Last Seen", "series": "Seriale"
"now": "Now",
"years": "{{number}}y",
"weeks": "{{number}}w",
"days": "{{number}}d",
"hours": "{{number}}h",
"minutes": "{{number}}m",
"seconds": "{{number}}s",
"ago": "{{value}} Ago"
},
"qnap": {
"cpuUsage": "CPU Usage",
"memUsage": "MEM Usage",
"systemTempC": "System Temp",
"poolUsage": "Pool Usage",
"volumeUsage": "Volume Usage",
"invalid": "Invalid"
},
"pfsense": {
"load": "Load Avg",
"memory": "Mem Usage",
"wanStatus": "WAN Status",
"up": "Up",
"down": "Down",
"temp": "Temp",
"disk": "Disk Usage",
"wanIP": "WAN IP"
},
"caddy": {
"upstreams": "Upstreams",
"requests": "Current requests",
"requests_failed": "Failed requests"
},
"evcc": {
"pv_power": "Production",
"battery_soc": "Battery",
"grid_power": "Grid",
"home_power": "Consumption",
"charge_power": "Charger",
"watt_hour": "Wh"
},
"pialert": {
"total": "Total",
"connected": "Connected",
"new_devices": "New Devices",
"down_alerts": "Down Alerts"
}, },
"jdownloader": { "jdownloader": {
"downloadCount": "Queue Count", "downloadCount": "Kolejka",
"downloadSpeed": "Download Speed", "downloadBytesRemaining": "Pozostało",
"downloadBytesRemaining": "Remaining", "downloadTotalBytes": "Rozmiar",
"downloadTotalBytes": "Size" "downloadSpeed": "Prędkość"
}, },
"kavita": { "kavita": {
"seriesCount": "Series", "seriesCount": "Seriale",
"totalFiles": "Files" "totalFiles": "Pliki"
},
"gamedig": {
"name": "Name",
"map": "Map",
"currentPlayers": "Current players",
"players": "Players",
"maxPlayers": "Max players",
"bots": "Bots",
"ping": "Ping",
"status": "Status",
"online": "Online",
"offline": "Offline"
}, },
"azuredevops": { "azuredevops": {
"status": "Status", "result": "Result",
"status": "Stan",
"buildId": "Build ID", "buildId": "Build ID",
"succeeded": "Succeeded", "succeeded": "Succeeded",
"notStarted": "Not Started", "notStarted": "Not Started",
"failed": "Failed", "failed": "Niepowodzenie",
"myPrs": "My PRs",
"approved": "Approved",
"result": "Result",
"canceled": "Canceled", "canceled": "Canceled",
"inProgress": "In Progress", "inProgress": "In Progress",
"totalPrs": "Total PRs" "totalPrs": "Total PRs",
"myPrs": "My PRs",
"approved": "Zaakceptowane"
},
"gamedig": {
"status": "Stan",
"online": "Online",
"offline": "Offline",
"name": "Nazwa",
"map": "Mapa",
"currentPlayers": "Current players",
"players": "Gracze",
"maxPlayers": "Max players",
"bots": "Boty",
"ping": "Ping"
}, },
"urbackup": { "urbackup": {
"ok": "Ok", "ok": "Ok",
@@ -694,55 +725,37 @@
"noRecent": "Out of Date", "noRecent": "Out of Date",
"totalUsed": "Used Storage" "totalUsed": "Used Storage"
}, },
"openmediavault": {
"downloading": "Downloading",
"total": "Total",
"running": "Running",
"stopped": "Stopped",
"passed": "Passed",
"failed": "Failed"
},
"mealie": { "mealie": {
"recipes": "Recipes", "recipes": "Recipes",
"users": "Users", "users": "Użytkownicy",
"categories": "Categories", "categories": "Categories",
"tags": "Tags" "tags": "Tagi"
}, },
"atsumeru": { "openmediavault": {
"series": "Series", "downloading": "Downloading",
"archives": "Archives", "total": "Całkowite",
"chapters": "Chapters", "running": "Działa",
"categories": "Categories" "stopped": "Zatrzymane",
}, "passed": "Powodzenie",
"calibreweb": { "failed": "Niepowodzenie"
"books": "Books",
"authors": "Authors",
"categories": "Categories",
"series": "Series"
}, },
"uptimerobot": { "uptimerobot": {
"status": "Status", "status": "Stan",
"uptime": "Uptime", "uptime": "Czas działania",
"lastDown": "Last Downtime", "lastDown": "Last Downtime",
"downDuration": "Downtime Duration", "downDuration": "Downtime Duration",
"sitesUp": "Sites Up", "sitesUp": "Sites Up",
"sitesDown": "Sites Down", "sitesDown": "Niedziałające strony",
"paused": "Paused", "paused": "Zatrzymane",
"notyetchecked": "Not Yet Checked", "notyetchecked": "Not Yet Checked",
"up": "Up", "up": "Up",
"seemsdown": "Seems Down", "seemsdown": "Seems Down",
"down": "Down", "down": "Down",
"unknown": "Unknown" "unknown": "Nieznany"
},
"opendtu": {
"relativePower": "Power %",
"yieldDay": "Today",
"limit": "Limit",
"absolutePower": "Power"
}, },
"calendar": { "calendar": {
"physicalRelease": "Physical release",
"inCinemas": "In cinemas", "inCinemas": "In cinemas",
"physicalRelease": "Physical release",
"digitalRelease": "Digital release" "digitalRelease": "Digital release"
} }
} }

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Erro", "error": "Erro",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passou", "passed": "Passou",

View File

@@ -395,7 +395,9 @@
}, },
"ping": { "ping": {
"error": "Erro", "error": "Erro",
"ping": "Tempo de resposta" "ping": "Tempo de resposta",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Aprovado", "passed": "Aprovado",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Ошибка", "error": "Ошибка",
"ping": "Пинг" "ping": "Пинг",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"failed": "Неудачно", "failed": "Неудачно",

View File

@@ -195,7 +195,9 @@
}, },
"ping": { "ping": {
"error": "Chyba", "error": "Chyba",
"ping": "Odozva" "ping": "Odozva",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Prehrávané", "playing": "Prehrávané",

View File

@@ -152,7 +152,9 @@
}, },
"ping": { "ping": {
"error": "Napaka", "error": "Napaka",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Predvaja", "playing": "Predvaja",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

View File

@@ -107,7 +107,9 @@
}, },
"ping": { "ping": {
"error": "ข้อผิดพลาด", "error": "ข้อผิดพลาด",
"ping": "ปิง" "ping": "ปิง",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "กำลังเล่น", "playing": "กำลังเล่น",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Hata", "error": "Hata",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Geçti", "passed": "Geçti",

View File

@@ -172,7 +172,9 @@
}, },
"ping": { "ping": {
"error": "Помилка", "error": "Помилка",
"ping": "Пінг" "ping": "Пінг",
"up": "Up",
"down": "Down"
}, },
"emby": { "emby": {
"playing": "Відтворення", "playing": "Відтворення",

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "Error", "error": "Error",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Passed",

File diff suppressed because it is too large Load Diff

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "错误", "error": "错误",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "通过", "passed": "通过",

View File

@@ -0,0 +1,761 @@
{
"common": {
"bytes": "{{value, bytes}}",
"bits": "{{value, bytes(bits: true)}}",
"bbytes": "{{value, bytes(binary: true)}}",
"bbits": "{{value, bytes(bits: true; binary: true)}}",
"byterate": "{{value, rate(bits: false)}}",
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bitrate": "{{value, rate(bits: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}",
"percent": "{{value, percent}}",
"number": "{{value, number}}",
"ms": "{{value, number}}"
},
"widget": {
"missing_type": "缺失的组件类型: {{type}}",
"api_error": "API 错误",
"information": "信息",
"status": "状态",
"url": "URL",
"raw_error": "原始信息错误",
"response_data": "响应数据"
},
"weather": {
"current": "当前位置",
"allow": "点击以允许",
"updating": "更新中",
"wait": "请稍候"
},
"search": {
"placeholder": "搜索…"
},
"resources": {
"cpu": "CPU",
"mem": "内存",
"total": "总计",
"free": "空闲",
"used": "已使用",
"load": "负载",
"temp": "温度",
"max": "最大",
"uptime": "运行时间",
"months": "月",
"days": "日",
"hours": "时",
"minutes": "分"
},
"unifi": {
"users": "用户数",
"uptime": "系统运行时间",
"days": "天",
"wan": "WAN",
"lan": "LAN",
"wlan": "WLAN",
"devices": "设备",
"lan_devices": "LAN设备",
"wlan_devices": "WLAN 设备",
"lan_users": "LAN 用户",
"wlan_users": "WLAN 用户",
"up": "运行时间",
"down": "离线",
"wait": "请稍候",
"empty_data": "子系统状态未知"
},
"docker": {
"rx": "接收",
"tx": "发送",
"mem": "内存",
"cpu": "CPU",
"running": "运行中",
"offline": "离线",
"error": "错误",
"unknown": "未知",
"healthy": "健康",
"starting": "启动中",
"unhealthy": "不健康",
"not_found": "未找到",
"exited": "已退出",
"partial": "部分"
},
"ping": {
"http_status": "HTTP 状态",
"error": "错误",
"ping": "Ping",
"down": "离线",
"up": "在线",
"not_available": "不可用"
},
"emby": {
"playing": "正在播放",
"transcoding": "转码中",
"bitrate": "码率",
"no_active": "无活动流",
"movies": "电影",
"series": "剧集",
"episodes": "集",
"songs": "曲目"
},
"evcc": {
"pv_power": "发电量",
"battery_soc": "电量",
"grid_power": "电网功率",
"home_power": "全屋功率",
"charge_power": "充电功率",
"watt_hour": "Wh"
},
"flood": {
"download": "下载速率",
"upload": "上传速率",
"leech": "下载中",
"seed": "做种中"
},
"freshrss": {
"subscriptions": "订阅",
"unread": "未读"
},
"caddy": {
"upstreams": "上行",
"requests": "当前请求",
"requests_failed": "失败请求"
},
"changedetectionio": {
"totalObserved": "总监测数",
"diffsDetected": "监测到的变更"
},
"channelsdvrserver": {
"shows": "剧集",
"recordings": "录制中",
"scheduled": "已预约",
"passes": "通行证"
},
"tautulli": {
"playing": "正在播放",
"transcoding": "转码中",
"bitrate": "码率",
"no_active": "无活动流",
"plex_connection_error": "检查Plex连接"
},
"omada": {
"connectedAp": "已连接的 AP",
"activeUser": "活跃的设备",
"alerts": "警告",
"connectedGateway": "已连接的网关",
"connectedSwitches": "已连接的开关"
},
"nzbget": {
"rate": "速率",
"remaining": "剩余时间",
"downloaded": "已下载"
},
"plex": {
"streams": "活动流",
"albums": "专辑",
"movies": "电影",
"tv": "剧集"
},
"sabnzbd": {
"rate": "速率",
"queue": "队列",
"timeleft": "剩余时间"
},
"rutorrent": {
"active": "活动中",
"upload": "上传速率",
"download": "下载速率"
},
"transmission": {
"download": "下载速率",
"upload": "上传速率",
"leech": "下载中",
"seed": "做种中"
},
"qbittorrent": {
"download": "下载速率",
"upload": "上传速率",
"leech": "下载中",
"seed": "做种中"
},
"qnap": {
"cpuUsage": "CPU 使用率",
"memUsage": "内存使用率",
"systemTempC": "系统温度",
"poolUsage": "存储池使用情况",
"volumeUsage": "分卷使用率",
"invalid": "无效的"
},
"deluge": {
"download": "下载速率",
"upload": "上传速率",
"leech": "下载中",
"seed": "做种中"
},
"downloadstation": {
"download": "下载速率",
"upload": "上传速率",
"leech": "下载中",
"seed": "做种中"
},
"sonarr": {
"wanted": "关注中",
"queued": "已加入队列",
"series": "剧集",
"queue": "队列",
"unknown": "未知"
},
"radarr": {
"wanted": "关注中",
"missing": "缺失",
"queued": "已加入队列",
"movies": "电影",
"queue": "队列",
"unknown": "未知"
},
"lidarr": {
"wanted": "关注中",
"queued": "已加入队列",
"artists": "艺术家"
},
"readarr": {
"wanted": "关注中",
"queued": "已加入队列",
"books": "书籍"
},
"bazarr": {
"missingEpisodes": "缺少剧集",
"missingMovies": "缺少电影"
},
"ombi": {
"pending": "等待中",
"approved": "已批准",
"available": "可用"
},
"jellyseerr": {
"pending": "等待中",
"approved": "已批准",
"available": "可用"
},
"overseerr": {
"pending": "等待中",
"processing": "处理中",
"approved": "已批准",
"available": "可用"
},
"pialert": {
"total": "总计",
"connected": "已连接",
"new_devices": "新设备",
"down_alerts": "离线警报"
},
"pihole": {
"queries": "查询",
"blocked": "已屏蔽",
"blocked_percent": "已屏蔽 %",
"gravity": "屏蔽列表"
},
"adguard": {
"queries": "查询",
"blocked": "已屏蔽",
"filtered": "已过滤",
"latency": "延迟"
},
"speedtest": {
"upload": "上传速率",
"download": "下载速率",
"ping": "Ping"
},
"portainer": {
"running": "运行中",
"stopped": "已停止",
"total": "总计"
},
"tailscale": {
"address": "地址",
"expires": "失效",
"never": "从未",
"last_seen": "最后上线",
"now": "当前",
"years": "{{number}}年",
"weeks": "{{number}}周",
"days": "{{number}}天",
"hours": "{{number}}时",
"minutes": "{{number}}分",
"seconds": "{{number}}秒",
"ago": "{{value}} 之前"
},
"tdarr": {
"queue": "队列",
"processed": "已处理",
"errored": "错误",
"saved": "已保存"
},
"traefik": {
"routers": "路由",
"services": "服务",
"middleware": "中间件"
},
"navidrome": {
"nothing_streaming": "无活动流",
"please_wait": "请稍候"
},
"npm": {
"enabled": "启用",
"disabled": "禁用",
"total": "总计"
},
"coinmarketcap": {
"configure": "配置一个或多个加密货币进行跟踪",
"1hour": "1 小时",
"1day": "1 天",
"7days": "7 天",
"30days": "30 天"
},
"gotify": {
"apps": "应用",
"clients": "客户端",
"messages": "消息"
},
"prowlarr": {
"enableIndexers": "索引器",
"numberOfGrabs": "抓取",
"numberOfQueries": "查询",
"numberOfFailGrabs": "抓取失败",
"numberOfFailQueries": "查询失败"
},
"jackett": {
"configured": "已配置",
"errored": "错误"
},
"strelaysrv": {
"numActiveSessions": "会话",
"numConnections": "连接数",
"dataRelayed": "中继",
"transferRate": "速率"
},
"mastodon": {
"user_count": "用户数",
"status_count": "文章",
"domain_count": "域名"
},
"medusa": {
"wanted": "关注中",
"queued": "已加入队列",
"series": "剧集"
},
"minecraft": {
"players": "玩家",
"version": "版本",
"status": "状态",
"up": "在线",
"down": "离线"
},
"miniflux": {
"read": "已读",
"unread": "未读"
},
"authentik": {
"users": "用户数",
"loginsLast24H": "登录 (24小时)",
"failedLoginsLast24H": "登录失败 (24小时)"
},
"proxmox": {
"mem": "内存",
"cpu": "CPU",
"lxc": "LXC",
"vms": "VMs"
},
"glances": {
"cpu": "CPU",
"load": "负载",
"wait": "请稍候",
"temp": "温度",
"_temp": "温度",
"warn": "警告",
"uptime": "运行时间",
"total": "总计",
"free": "空闲",
"used": "已使用",
"days": "日",
"hours": "时",
"crit": "严重",
"read": "已读",
"write": "写入",
"gpu": "GPU",
"mem": "内存",
"swap": "Swap"
},
"quicklaunch": {
"bookmark": "书签",
"service": "服务",
"search": "搜索",
"custom": "自定义",
"visit": "访问",
"url": "URL"
},
"wmo": {
"0-day": "晴天",
"0-night": "晴朗",
"1-day": "晴天为主",
"1-night": "晴朗为主",
"2-day": "局部多云",
"2-night": "局部多云",
"3-day": "多云",
"3-night": "多云",
"45-day": "雾",
"45-night": "雾",
"48-day": "雾",
"48-night": "雾",
"51-day": "小细雨",
"51-night": "小细雨",
"53-day": "细雨",
"53-night": "细雨",
"55-day": "大细雨",
"55-night": "大细雨",
"56-day": "小冻细雨",
"56-night": "小冻细雨",
"57-day": "冻细雨",
"57-night": "冻细雨",
"61-day": "小雨",
"61-night": "小雨",
"63-day": "雨",
"63-night": "雨",
"65-day": "大雨",
"65-night": "大雨",
"66-day": "冻雨",
"66-night": "冻雨",
"67-day": "冻雨",
"67-night": "冻雨",
"71-day": "小雪",
"71-night": "小雪",
"73-day": "雪",
"73-night": "雪",
"75-day": "大雪",
"75-night": "大雪",
"77-day": "雪粒",
"77-night": "雪粒",
"80-day": "小阵雨",
"80-night": "小阵雨",
"81-day": "阵雨",
"81-night": "阵雨",
"82-day": "强阵雨",
"82-night": "强阵雨",
"85-day": "阵雪",
"85-night": "阵雪",
"86-day": "阵雪",
"86-night": "阵雪",
"95-day": "雷雨",
"95-night": "雷雨",
"96-day": "雷暴夹冰雹",
"96-night": "雷暴夹冰雹",
"99-day": "雷暴夹冰雹",
"99-night": "雷暴夹冰雹"
},
"homebridge": {
"available_update": "系统",
"updates": "更新",
"update_available": "有可用更新",
"up_to_date": "已是最新版本",
"child_bridges": "子网桥",
"child_bridges_status": "{{ok}}/{{total}}",
"up": "在线",
"pending": "等待中",
"down": "离线"
},
"healthchecks": {
"new": "新增",
"up": "在线",
"grace": "处于宽限期",
"down": "离线",
"paused": "已暂停",
"status": "状态",
"last_ping": "上次 Ping",
"never": "尚未 Ping"
},
"watchtower": {
"containers_scanned": "已扫描",
"containers_updated": "已更新",
"containers_failed": "失败"
},
"autobrr": {
"approvedPushes": "已批准",
"rejectedPushes": "拒绝",
"filters": "过滤器",
"indexers": "索引器"
},
"tubearchivist": {
"downloads": "队列",
"videos": "视频",
"channels": "频道",
"playlists": "播放列表"
},
"truenas": {
"load": "系统负载",
"uptime": "运行时间",
"alerts": "警告",
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
},
"pyload": {
"speed": "速度",
"active": "活动中",
"queue": "队列",
"total": "总计"
},
"gluetun": {
"public_ip": "公网 IP",
"region": "地区",
"country": "国家"
},
"hdhomerun": {
"channels": "频道",
"hd": "HD"
},
"scrutiny": {
"passed": "通过",
"failed": "失败",
"unknown": "未知"
},
"paperlessngx": {
"inbox": "收件箱",
"total": "总计"
},
"nextdns": {
"wait": "请稍候",
"no_devices": "未收到设备数据"
},
"mikrotik": {
"cpuLoad": "CPU 负载",
"memoryUsed": "内存占用",
"uptime": "运行时间",
"numberOfLeases": "租约"
},
"xteve": {
"streams_all": "所有流",
"streams_active": "活动流",
"streams_xepg": "XEPG 频道"
},
"opendtu": {
"yieldDay": "今日",
"absolutePower": "功率",
"relativePower": "功率 %",
"limit": "限制"
},
"opnsense": {
"cpu": "CPU 负载",
"memory": "活动内存",
"wanUpload": "WAN 上传",
"wanDownload": "WAN 下载"
},
"moonraker": {
"printer_state": "打印机状态",
"print_status": "打印状态",
"print_progress": "进度",
"layers": "层"
},
"octoprint": {
"printer_state": "状态",
"temp_tool": "喷头温度",
"temp_bed": "热床温度",
"job_completion": "完成"
},
"cloudflared": {
"origin_ip": "来源 IP",
"status": "状态"
},
"pfsense": {
"load": "平均负载",
"memory": "内存使用率",
"wanStatus": "WAN 状态",
"up": "在线",
"down": "离线",
"temp": "温度",
"disk": "磁盘使用量",
"wanIP": "WAN IP"
},
"proxmoxbackupserver": {
"datastore_usage": "数据存储",
"failed_tasks_24h": "24小时内失败任务",
"cpu_usage": "CPU",
"memory_usage": "内存"
},
"immich": {
"users": "用户数",
"photos": "照片",
"videos": "视频",
"storage": "存储空间"
},
"uptimekuma": {
"up": "在线网站",
"down": "离线网站",
"uptime": "运行时间",
"incident": "事件",
"m": "分"
},
"atsumeru": {
"series": "剧集",
"archives": "存档",
"chapters": "章节",
"categories": "类别"
},
"komga": {
"libraries": "库",
"series": "剧集",
"books": "书籍"
},
"diskstation": {
"days": "天",
"uptime": "运行时间",
"volumeAvailable": "可用"
},
"mylar": {
"series": "剧集",
"issues": "出版",
"wanted": "关注中"
},
"photoprism": {
"albums": "专辑",
"photos": "照片",
"videos": "视频",
"people": "人物"
},
"fileflows": {
"queue": "队列",
"processing": "处理中",
"processed": "已处理",
"time": "时间"
},
"grafana": {
"dashboards": "仪表板",
"datasources": "数据源",
"totalalerts": "警告总数",
"alertstriggered": "触发警告"
},
"nextcloud": {
"cpuload": "CPU 负载",
"memoryusage": "内存使用量",
"freespace": "剩余空间",
"activeusers": "活动用户",
"numfiles": "文件",
"numshares": "已共享项目"
},
"kopia": {
"status": "状态",
"size": "大小",
"lastrun": "上一次运行",
"nextrun": "下一次运行",
"failed": "失败"
},
"unmanic": {
"active_workers": "活动工作程序",
"total_workers": "总工作程序",
"records_total": "队列长度"
},
"pterodactyl": {
"servers": "服务器",
"nodes": "节点"
},
"prometheus": {
"targets_up": "上线目标",
"targets_down": "离线目标",
"targets_total": "目标总数"
},
"ghostfolio": {
"gross_percent_today": "今日",
"gross_percent_1y": "1年",
"gross_percent_max": "所有时间"
},
"audiobookshelf": {
"podcasts": "播客",
"books": "书籍",
"podcastsDuration": "时长",
"booksDuration": "时长"
},
"homeassistant": {
"people_home": "在家人数",
"lights_on": "灯光开启",
"switches_on": "开关开启"
},
"whatsupdocker": {
"monitoring": "监测中",
"updates": "更新"
},
"calibreweb": {
"books": "书籍",
"authors": "作者",
"categories": "类别",
"series": "剧集"
},
"jdownloader": {
"downloadCount": "队列",
"downloadBytesRemaining": "剩余时间",
"downloadTotalBytes": "大小",
"downloadSpeed": "速度"
},
"kavita": {
"seriesCount": "剧集",
"totalFiles": "文件"
},
"azuredevops": {
"result": "结果",
"status": "状态",
"buildId": "构建 ID",
"succeeded": "成功",
"notStarted": "尚未开始",
"failed": "失败",
"canceled": "已取消",
"inProgress": "处理中",
"totalPrs": "总 PR",
"myPrs": "我的 PR",
"approved": "已批准"
},
"gamedig": {
"status": "状态",
"online": "在线",
"offline": "离线",
"name": "名称",
"map": "地图",
"currentPlayers": "当前玩家",
"players": "玩家",
"maxPlayers": "玩家上限",
"bots": "机器人",
"ping": "Ping"
},
"urbackup": {
"ok": "成功",
"errored": "错误",
"noRecent": "已过期",
"totalUsed": "使用的存储"
},
"mealie": {
"recipes": "食谱",
"users": "用户数",
"categories": "类别",
"tags": "标签"
},
"openmediavault": {
"downloading": "下载中",
"total": "总计",
"running": "运行中",
"stopped": "已停止",
"passed": "通过",
"failed": "失败"
},
"uptimerobot": {
"status": "状态",
"uptime": "运行时间",
"lastDown": "上次下线时间",
"downDuration": "下线时长",
"sitesUp": "在线网站",
"sitesDown": "离线网站",
"paused": "已暂停",
"notyetchecked": "尚未检查",
"up": "在线",
"seemsdown": "貌似离线",
"down": "离线",
"unknown": "未知"
},
"calendar": {
"inCinemas": "上映中",
"physicalRelease": "实体发行",
"digitalRelease": "数字发行"
}
}

View File

@@ -382,7 +382,9 @@
}, },
"ping": { "ping": {
"error": "錯誤", "error": "錯誤",
"ping": "Ping" "ping": "Ping",
"up": "Up",
"down": "Down"
}, },
"scrutiny": { "scrutiny": {
"passed": "通過", "passed": "通過",

View File

@@ -26,3 +26,4 @@ requests==2.31.0
six==1.16.0 six==1.16.0
urllib3==2.0.5 urllib3==2.0.5
watchdog==3.0.0 watchdog==3.0.0
pre-commit==3.5.0

View File

@@ -1,6 +1,6 @@
import { useRef } from "react"; import { useRef } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { Disclosure, Transition } from '@headlessui/react'; import { Disclosure, Transition } from "@headlessui/react";
import { MdKeyboardArrowDown } from "react-icons/md"; import { MdKeyboardArrowDown } from "react-icons/md";
import ErrorBoundary from "components/errorboundry"; import ErrorBoundary from "components/errorboundry";
@@ -15,7 +15,7 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse }) {
className={classNames( className={classNames(
"bookmark-group", "bookmark-group",
layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6",
layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1" layout?.header === false ? "flex-1 px-1 -my-1" : "flex-1 p-1",
)} )}
> >
<Disclosure defaultOpen> <Disclosure defaultOpen>
@@ -28,12 +28,14 @@ export default function BookmarksGroup({ bookmarks, layout, disableCollapse }) {
<ResolvedIcon icon={layout.icon} /> <ResolvedIcon icon={layout.icon} />
</div> </div>
)} )}
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium bookmark-group-name">{bookmarks.name}</h2> <h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium bookmark-group-name">
{bookmarks.name}
</h2>
<MdKeyboardArrowDown <MdKeyboardArrowDown
className={classNames( className={classNames(
disableCollapse ? "hidden" : "", disableCollapse ? "hidden" : "",
"transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl", "transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl",
open ? "" : "rotate-180" open ? "" : "rotate-180",
)} )}
/> />
</Disclosure.Button> </Disclosure.Button>

View File

@@ -15,22 +15,24 @@ export default function Item({ bookmark }) {
title={bookmark.name} title={bookmark.name}
target={bookmark.target ?? settings.target ?? "_blank"} target={bookmark.target ?? settings.target ?? "_blank"}
className={classNames( className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`, settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`,
"block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10" "block w-full text-left cursor-pointer transition-all h-15 mb-3 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10",
)} )}
> >
<div className="flex"> <div className="flex">
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md bookmark-icon"> <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md bookmark-icon">
{bookmark.icon && {bookmark.icon && (
<div className="flex-shrink-0 w-5 h-5"> <div className="flex-shrink-0 w-5 h-5">
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} /> <ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
</div> </div>
} )}
{!bookmark.icon && bookmark.abbr} {!bookmark.icon && bookmark.abbr}
</div> </div>
<div className="flex-1 flex items-center justify-between rounded-r-md bookmark-text"> <div className="flex-1 flex items-center justify-between rounded-r-md bookmark-text">
<div className="flex-1 grow pl-3 py-2 text-xs bookmark-name">{bookmark.name}</div> <div className="flex-1 grow pl-3 py-2 text-xs bookmark-name">{bookmark.name}</div>
<div className="px-2 py-2 truncate text-theme-500 dark:text-theme-300 text-xs bookmark-description">{description}</div> <div className="px-2 py-2 truncate text-theme-500 dark:text-theme-300 text-xs bookmark-description">
{description}
</div>
</div> </div>
</div> </div>
</a> </a>

View File

@@ -9,7 +9,7 @@ export default function List({ bookmarks, layout }) {
<ul <ul
className={classNames( className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col", layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3 bookmark-list" "mt-3 bookmark-list",
)} )}
> >
{bookmarks.map((bookmark) => ( {bookmarks.map((bookmark) => (

View File

@@ -1,10 +1,10 @@
import useSWR from "swr" import useSWR from "swr";
export default function FileContent({ path, loadingValue, errorValue, emptyValue = '' }) { export default function FileContent({ path, loadingValue, errorValue, emptyValue = "" }) {
const fetcher = (url) => fetch(url).then((res) => res.text()) const fetcher = (url) => fetch(url).then((res) => res.text());
const { data, error, isLoading } = useSWR(`/api/config/${ path }`, fetcher) const { data, error, isLoading } = useSWR(`/api/config/${path}`, fetcher);
if (error) return (errorValue) if (error) return errorValue;
if (isLoading) return (loadingValue) if (isLoading) return loadingValue;
return (data || emptyValue) return data || emptyValue;
} }

View File

@@ -6,10 +6,19 @@ import ResolvedIcon from "./resolvedicon";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close, searchProvider}) { export default function QuickLaunch({
servicesAndBookmarks,
searchString,
setSearchString,
isOpen,
close,
searchProvider,
}) {
const { t } = useTranslation(); const { t } = useTranslation();
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
const { searchDescriptions, hideVisitURL } = settings?.quicklaunch ? settings.quicklaunch : { searchDescriptions: false, hideVisitURL: false }; const { searchDescriptions, hideVisitURL } = settings?.quicklaunch
? settings.quicklaunch
: { searchDescriptions: false, hideVisitURL: false };
const searchField = useRef(); const searchField = useRef();
@@ -19,7 +28,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
function openCurrentItem(newWindow) { function openCurrentItem(newWindow) {
const result = results[currentItemIndex]; const result = results[currentItemIndex];
window.open(result.href, newWindow ? "_blank" : result.target ?? settings.target ?? "_blank", 'noreferrer'); window.open(result.href, newWindow ? "_blank" : result.target ?? settings.target ?? "_blank", "noreferrer");
} }
const closeAndReset = useCallback(() => { const closeAndReset = useCallback(() => {
@@ -35,7 +44,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
try { try {
if (!/.+[.:].+/g.test(rawSearchString)) throw new Error(); // basic test for probably a url if (!/.+[.:].+/g.test(rawSearchString)) throw new Error(); // basic test for probably a url
let urlString = rawSearchString; let urlString = rawSearchString;
if (urlString.indexOf('http') !== 0) urlString = `https://${rawSearchString}`; if (urlString.indexOf("http") !== 0) urlString = `https://${rawSearchString}`;
setUrl(new URL(urlString)); // basic validation setUrl(new URL(urlString)); // basic validation
} catch (e) { } catch (e) {
setUrl(null); setUrl(null);
@@ -83,12 +92,12 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
useEffect(() => { useEffect(() => {
if (searchString.length === 0) setResults([]); if (searchString.length === 0) setResults([]);
else { else {
let newResults = servicesAndBookmarks.filter(r => { let newResults = servicesAndBookmarks.filter((r) => {
const nameMatch = r.name.toLowerCase().includes(searchString); const nameMatch = r.name.toLowerCase().includes(searchString);
let descriptionMatch; let descriptionMatch;
if (searchDescriptions) { if (searchDescriptions) {
descriptionMatch = r.description?.toLowerCase().includes(searchString) descriptionMatch = r.description?.toLowerCase().includes(searchString);
r.priority = nameMatch ? 2 * (+nameMatch) : +descriptionMatch; // eslint-disable-line no-param-reassign r.priority = nameMatch ? 2 * +nameMatch : +descriptionMatch; // eslint-disable-line no-param-reassign
} }
return nameMatch || descriptionMatch; return nameMatch || descriptionMatch;
}); });
@@ -98,23 +107,19 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
} }
if (searchProvider) { if (searchProvider) {
newResults.push( newResults.push({
{
href: searchProvider.url + encodeURIComponent(searchString), href: searchProvider.url + encodeURIComponent(searchString),
name: `${searchProvider.name ?? t("quicklaunch.custom")} ${t("quicklaunch.search")} `, name: `${searchProvider.name ?? t("quicklaunch.custom")} ${t("quicklaunch.search")} `,
type: 'search', type: "search",
} });
)
} }
if (!hideVisitURL && url) { if (!hideVisitURL && url) {
newResults.unshift( newResults.unshift({
{
href: url.toString(), href: url.toString(),
name: `${t("quicklaunch.visit")} URL`, name: `${t("quicklaunch.visit")} URL`,
type: 'url', type: "url",
} });
)
} }
setResults(newResults); setResults(newResults);
@@ -125,7 +130,6 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
} }
}, [searchString, servicesAndBookmarks, searchDescriptions, hideVisitURL, searchProvider, url, t]); }, [searchString, servicesAndBookmarks, searchDescriptions, hideVisitURL, searchProvider, url, t]);
const [hidden, setHidden] = useState(true); const [hidden, setHidden] = useState(true);
useEffect(() => { useEffect(() => {
function handleBackdropClick(event) { function handleBackdropClick(event) {
@@ -134,66 +138,103 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
if (isOpen) { if (isOpen) {
searchField.current.focus(); searchField.current.focus();
document.body.addEventListener('click', handleBackdropClick); document.body.addEventListener("click", handleBackdropClick);
setHidden(false); setHidden(false);
} else { } else {
document.body.removeEventListener('click', handleBackdropClick); document.body.removeEventListener("click", handleBackdropClick);
searchField.current.blur(); searchField.current.blur();
setTimeout(() => { setTimeout(() => {
setHidden(true); setHidden(true);
}, 300); // disable on close }, 300); // disable on close
} }
}, [isOpen, closeAndReset]); }, [isOpen, closeAndReset]);
function highlightText(text) { function highlightText(text) {
const parts = text.split(new RegExp(`(${searchString})`, 'gi')); const parts = text.split(new RegExp(`(${searchString})`, "gi"));
return (
<span>
{parts.map((part, i) =>
part.toLowerCase() === searchString.toLowerCase() ? (
// eslint-disable-next-line react/no-array-index-key // eslint-disable-next-line react/no-array-index-key
return <span>{parts.map((part, i) => part.toLowerCase() === searchString.toLowerCase() ? <span key={`${searchString}_${i}`} className="bg-theme-300/10">{part}</span> : part)}</span>; <span key={`${searchString}_${i}`} className="bg-theme-300/10">
{part}
</span>
) : (
part
),
)}
</span>
);
} }
return ( return (
<div className={classNames( <div
className={classNames(
"relative z-40 ease-in-out duration-300 transition-opacity", "relative z-40 ease-in-out duration-300 transition-opacity",
hidden && !isOpen && "hidden", hidden && !isOpen && "hidden",
!hidden && isOpen && "opacity-100", !hidden && isOpen && "opacity-100",
!isOpen && "opacity-0", !isOpen && "opacity-0",
)} role="dialog" aria-modal="true"> )}
role="dialog"
aria-modal="true"
>
<div className="fixed inset-0 bg-gray-500 bg-opacity-50" /> <div className="fixed inset-0 bg-gray-500 bg-opacity-50" />
<div className="fixed inset-0 z-20 overflow-y-auto"> <div className="fixed inset-0 z-20 overflow-y-auto">
<div className="flex min-h-full min-w-full items-start justify-center text-center"> <div className="flex min-h-full min-w-full items-start justify-center text-center">
<dialog className="mt-[10%] min-w-[80%] max-w-[90%] md:min-w-[40%] rounded-md p-0 block font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-50 dark:bg-theme-800"> <dialog className="mt-[10%] min-w-[80%] max-w-[90%] md:min-w-[40%] rounded-md p-0 block font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-50 dark:bg-theme-800">
<input placeholder="Search" className={classNames( <input
placeholder="Search"
className={classNames(
results.length > 0 && "rounded-t-md", results.length > 0 && "rounded-t-md",
results.length === 0 && "rounded-md", results.length === 0 && "rounded-md",
"w-full p-4 m-0 border-0 border-b border-slate-700 focus:border-slate-700 focus:outline-0 focus:ring-0 text-sm md:text-xl text-theme-700 dark:text-theme-200 bg-theme-60 dark:bg-theme-800" "w-full p-4 m-0 border-0 border-b border-slate-700 focus:border-slate-700 focus:outline-0 focus:ring-0 text-sm md:text-xl text-theme-700 dark:text-theme-200 bg-theme-60 dark:bg-theme-800",
)} type="text" autoCorrect="false" ref={searchField} value={searchString} onChange={handleSearchChange} onKeyDown={handleSearchKeyDown} /> )}
{results.length > 0 && <ul className="max-h-[60vh] overflow-y-auto m-2"> type="text"
autoCorrect="false"
ref={searchField}
value={searchString}
onChange={handleSearchChange}
onKeyDown={handleSearchKeyDown}
/>
{results.length > 0 && (
<ul className="max-h-[60vh] overflow-y-auto m-2">
{results.map((r, i) => ( {results.map((r, i) => (
<li key={r.container ?? r.app ?? `${r.name}-${r.href}`}> <li key={r.container ?? r.app ?? `${r.name}-${r.href}`}>
<button type="button" data-index={i} onMouseEnter={handleItemHover} onClick={handleItemClick} onKeyDown={handleItemKeyDown} className={classNames( <button
type="button"
data-index={i}
onMouseEnter={handleItemHover}
onClick={handleItemClick}
onKeyDown={handleItemKeyDown}
className={classNames(
"flex flex-row w-full items-center justify-between rounded-md text-sm md:text-xl py-2 px-4 cursor-pointer text-theme-700 dark:text-theme-200", "flex flex-row w-full items-center justify-between rounded-md text-sm md:text-xl py-2 px-4 cursor-pointer text-theme-700 dark:text-theme-200",
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50", i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
)}> )}
>
<div className="flex flex-row items-center mr-4 pointer-events-none"> <div className="flex flex-row items-center mr-4 pointer-events-none">
{(r.icon || r.abbr) && <div className="w-5 text-xs mr-4"> {(r.icon || r.abbr) && (
<div className="w-5 text-xs mr-4">
{r.icon && <ResolvedIcon icon={r.icon} />} {r.icon && <ResolvedIcon icon={r.icon} />}
{r.abbr && r.abbr} {r.abbr && r.abbr}
</div>} </div>
)}
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none"> <div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
<span className="mr-4">{r.name}</span> <span className="mr-4">{r.name}</span>
{r.description && {r.description && (
<span className="text-xs text-theme-600 text-light"> <span className="text-xs text-theme-600 text-light">
{searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description} {searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description}
</span> </span>
} )}
</div> </div>
</div> </div>
<div className="text-xs text-theme-600 font-bold pointer-events-none">{t(`quicklaunch.${r.type ? r.type.toLowerCase() : 'bookmark'}`)}</div> <div className="text-xs text-theme-600 font-bold pointer-events-none">
{t(`quicklaunch.${r.type ? r.type.toLowerCase() : "bookmark"}`)}
</div>
</button> </button>
</li> </li>
))} ))}
</ul>} </ul>
)}
</dialog> </dialog>
</div> </div>
</div> </div>

View File

@@ -5,8 +5,8 @@ import { SettingsContext } from "utils/contexts/settings";
import { ThemeContext } from "utils/contexts/theme"; import { ThemeContext } from "utils/contexts/theme";
const iconSetURLs = { const iconSetURLs = {
'mdi': "https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/", mdi: "https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/",
'si' : "https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/", si: "https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/",
}; };
export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "logo" }) { export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "logo" }) {
@@ -38,12 +38,13 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
if (prefix in iconSetURLs) { if (prefix in iconSetURLs) {
// default to theme setting // default to theme setting
let iconName = icon.replace(`${prefix}-`, "").replace(".svg", ""); let iconName = icon.replace(`${prefix}-`, "").replace(".svg", "");
let iconColor = settings.iconStyle === "theme" ? let iconColor =
`rgb(var(--color-${ theme === "dark" ? 300 : 900 }) / var(--tw-text-opacity, 1))` : settings.iconStyle === "theme"
"linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))"; ? `rgb(var(--color-${theme === "dark" ? 300 : 900}) / var(--tw-text-opacity, 1))`
: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))";
// use custom hex color if provided // use custom hex color if provided
const colorMatches = icon.match(/[#][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/i) const colorMatches = icon.match(/[#][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/i);
if (colorMatches?.length) { if (colorMatches?.length) {
iconName = icon.replace(`${prefix}-`, "").replace(".svg", "").replace(`-${colorMatches[0]}`, ""); iconName = icon.replace(`${prefix}-`, "").replace(".svg", "").replace(`-${colorMatches[0]}`, "");
iconColor = `${colorMatches[0]}`; iconColor = `${colorMatches[0]}`;
@@ -56,8 +57,8 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
style={{ style={{
width, width,
height, height,
maxWidth: '100%', maxWidth: "100%",
maxHeight: '100%', maxHeight: "100%",
background: `${iconColor}`, background: `${iconColor}`,
mask: `url(${iconSource}) no-repeat center / contain`, mask: `url(${iconSource}) no-repeat center / contain`,
WebkitMask: `url(${iconSource}) no-repeat center / contain`, WebkitMask: `url(${iconSource}) no-repeat center / contain`,
@@ -79,7 +80,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
height, height,
objectFit: "contain", objectFit: "contain",
maxHeight: "100%", maxHeight: "100%",
maxWidth: "100%" maxWidth: "100%",
}} }}
alt={alt} alt={alt}
/> />
@@ -97,7 +98,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "log
height, height,
objectFit: "contain", objectFit: "contain",
maxHeight: "100%", maxHeight: "100%",
maxWidth: "100%" maxWidth: "100%",
}} }}
alt={alt} alt={alt}
/> />

View File

@@ -33,7 +33,7 @@ export default function Dropdown({ options, value, setValue }) {
type="button" type="button"
className={classNames( className={classNames(
value === option.value ? "bg-theme-300/40 dark:bg-theme-900/40" : "", value === option.value ? "bg-theme-300/40 dark:bg-theme-900/40" : "",
"w-full block px-3 py-1.5 text-sm hover:bg-theme-300/70 hover:dark:bg-theme-900/70 text-left" "w-full block px-3 py-1.5 text-sm hover:bg-theme-300/70 hover:dark:bg-theme-900/70 text-left",
)} )}
> >
{option.label} {option.label}

View File

@@ -1,13 +1,12 @@
import { useRef } from "react"; import { useRef } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { Disclosure, Transition } from '@headlessui/react'; import { Disclosure, Transition } from "@headlessui/react";
import { MdKeyboardArrowDown } from "react-icons/md"; import { MdKeyboardArrowDown } from "react-icons/md";
import List from "components/services/list"; import List from "components/services/list";
import ResolvedIcon from "components/resolvedicon"; import ResolvedIcon from "components/resolvedicon";
export default function ServicesGroup({ group, services, layout, fiveColumns, disableCollapse }) { export default function ServicesGroup({ group, services, layout, fiveColumns, disableCollapse }) {
const panel = useRef(); const panel = useRef();
return ( return (
@@ -23,33 +22,43 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
<Disclosure defaultOpen> <Disclosure defaultOpen>
{({ open }) => ( {({ open }) => (
<> <>
{ layout?.header !== false && {layout?.header !== false && (
<Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group"> <Disclosure.Button disabled={disableCollapse} className="flex w-full select-none items-center group">
{layout?.icon && {layout?.icon && (
<div className="flex-shrink-0 mr-2 w-7 h-7 service-group-icon"> <div className="flex-shrink-0 mr-2 w-7 h-7 service-group-icon">
<ResolvedIcon icon={layout.icon} /> <ResolvedIcon icon={layout.icon} />
</div> </div>
} )}
<h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name">{services.name}</h2> <h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium service-group-name">
<MdKeyboardArrowDown className={classNames( {services.name}
disableCollapse ? 'hidden' : '', </h2>
'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl', <MdKeyboardArrowDown
open ? '' : 'rotate-180' className={classNames(
)} /> disableCollapse ? "hidden" : "",
"transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl",
open ? "" : "rotate-180",
)}
/>
</Disclosure.Button> </Disclosure.Button>
} )}
<Transition <Transition
// Otherwise the transition group does display: none and cancels animation // Otherwise the transition group does display: none and cancels animation
className="!block" className="!block"
unmount={false} unmount={false}
beforeLeave={() => { beforeLeave={() => {
panel.current.style.height = `${panel.current.scrollHeight}px`; panel.current.style.height = `${panel.current.scrollHeight}px`;
setTimeout(() => {panel.current.style.height = `0`}, 1); setTimeout(() => {
panel.current.style.height = `0`;
}, 1);
}} }}
beforeEnter={() => { beforeEnter={() => {
panel.current.style.height = `0px`; panel.current.style.height = `0px`;
setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1); setTimeout(() => {
setTimeout(() => {panel.current.style.height = 'auto'}, 150); // animation is 150ms panel.current.style.height = `${panel.current.scrollHeight}px`;
}, 1);
setTimeout(() => {
panel.current.style.height = "auto";
}, 150); // animation is 150ms
}} }}
> >
<Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static> <Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>

View File

@@ -14,8 +14,8 @@ import ResolvedIcon from "components/resolvedicon";
export default function Item({ service, group }) { export default function Item({ service, group }) {
const hasLink = service.href && service.href !== "#"; const hasLink = service.href && service.href !== "#";
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
const showStats = (service.showStats === false) ? false : settings.showStats; const showStats = service.showStats === false ? false : settings.showStats;
const statusStyle = (service.statusStyle !== undefined) ? service.statusStyle : settings.statusStyle; const statusStyle = service.statusStyle !== undefined ? service.statusStyle : settings.statusStyle;
const [statsOpen, setStatsOpen] = useState(service.showStats); const [statsOpen, setStatsOpen] = useState(service.showStats);
const [statsClosing, setStatsClosing] = useState(false); const [statsClosing, setStatsClosing] = useState(false);
@@ -34,9 +34,9 @@ export default function Item({ service, group }) {
<li key={service.name} id={service.id} className="service" data-name={service.name || ""}> <li key={service.name} id={service.id} className="service" data-name={service.name || ""}>
<div <div
className={classNames( className={classNames(
settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? '-' : ""}${settings.cardBlur}`, settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`,
hasLink && "cursor-pointer", hasLink && "cursor-pointer",
"transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip service-card" "transition-all h-15 mb-2 p-1 rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10 relative overflow-clip service-card",
)} )}
> >
<div className="flex select-none z-0 service-title"> <div className="flex select-none z-0 service-title">
@@ -65,19 +65,27 @@ export default function Item({ service, group }) {
> >
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name"> <div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
{service.name} {service.name}
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p> <p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">
{service.description}
</p>
</div> </div>
</a> </a>
) : ( ) : (
<div className="flex-1 flex items-center justify-between rounded-r-md service-title-text"> <div className="flex-1 flex items-center justify-between rounded-r-md service-title-text">
<div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name"> <div className="flex-1 px-2 py-2 text-sm text-left z-10 service-name">
{service.name} {service.name}
<p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">{service.description}</p> <p className="text-theme-500 dark:text-theme-300 text-xs font-light service-description">
{service.description}
</p>
</div> </div>
</div> </div>
)} )}
<div className={`absolute top-0 right-0 flex flex-row justify-end ${statusStyle === 'dot' ? 'gap-0' : 'gap-2'} mr-2 z-30 service-tags`}> <div
className={`absolute top-0 right-0 flex flex-row justify-end ${
statusStyle === "dot" ? "gap-0" : "gap-2 mr-2"
} z-30 service-tags`}
>
{service.ping && ( {service.ping && (
<div className="flex-shrink-0 flex items-center justify-center service-tag service-ping"> <div className="flex-shrink-0 flex items-center justify-center service-tag service-ping">
<Ping group={group} service={service.name} style={statusStyle} /> <Ping group={group} service={service.name} style={statusStyle} />
@@ -95,7 +103,7 @@ export default function Item({ service, group }) {
<span className="sr-only">View container stats</span> <span className="sr-only">View container stats</span>
</button> </button>
)} )}
{(service.app && !service.external) && ( {service.app && !service.external && (
<button <button
type="button" type="button"
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))} onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
@@ -112,20 +120,28 @@ export default function Item({ service, group }) {
<div <div
className={classNames( className={classNames(
showStats || (statsOpen && !statsClosing) ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0", showStats || (statsOpen && !statsClosing) ? "max-h-[110px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats" "w-full overflow-hidden transition-all duration-300 ease-in-out service-stats",
)} )}
> >
{(showStats || statsOpen) && <Docker service={{ widget: { container: service.container, server: service.server } }} />} {(showStats || statsOpen) && (
<Docker service={{ widget: { container: service.container, server: service.server } }} />
)}
</div> </div>
)} )}
{service.app && ( {service.app && (
<div <div
className={classNames( className={classNames(
showStats || (statsOpen && !statsClosing) ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0", showStats || (statsOpen && !statsClosing) ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
"w-full overflow-hidden transition-all duration-300 ease-in-out service-stats" "w-full overflow-hidden transition-all duration-300 ease-in-out service-stats",
)} )}
> >
{(showStats || statsOpen) && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />} {(showStats || statsOpen) && (
<Kubernetes
service={{
widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector },
}}
/>
)}
</div> </div>
)} )}

View File

@@ -8,7 +8,7 @@ export default function KubernetesStatus({ service, style }) {
let statusLabel = t("docker.unknown"); let statusLabel = t("docker.unknown");
let statusTitle = ""; let statusTitle = "";
let backgroundClass = "px-1.5 py-0.5 bg-theme-500/10 dark:bg-theme-900/50"; let backgroundClass = "px-1.5 py-0.5 bg-theme-500/10 dark:bg-theme-900/50";
let colorClass = "text-black/20 dark:text-white/40 "; let colorClass = "text-black/20 dark:text-white/40 opacity-20";
if (error) { if (error) {
statusTitle = t("docker.error"); statusTitle = t("docker.error");
@@ -28,15 +28,21 @@ export default function KubernetesStatus({ service, style }) {
} }
} }
if (style === 'dot') { if (style === "dot") {
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, ''); colorClass = colorClass.replace(/text-/g, "bg-").replace(/\/\d\d/g, "");
backgroundClass = "p-3 hover:bg-theme-500/10 dark:hover:bg-theme-900/20"; backgroundClass = "p-4 hover:bg-theme-500/10 dark:hover:bg-theme-900/20";
} }
return ( return (
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] k8s-status`} title={statusTitle}> <div
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>} className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] k8s-status`}
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>} title={statusTitle}
>
{style !== "dot" ? (
<div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>
) : (
<div className={`rounded-full h-3 w-3 ${colorClass}`} />
)}
</div> </div>
); );
} }

View File

@@ -9,7 +9,7 @@ export default function List({ group, services, layout }) {
<ul <ul
className={classNames( className={classNames(
layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col", layout?.style === "row" ? `grid ${columnMap[layout?.columns]} gap-x-2` : "flex flex-col",
"mt-3 services-list" "mt-3 services-list",
)} )}
> >
{services.map((service) => ( {services.map((service) => (

View File

@@ -4,53 +4,55 @@ import useSWR from "swr";
export default function Ping({ group, service, style }) { export default function Ping({ group, service, style }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ group, service }).toString()}`, { const { data, error } = useSWR(`/api/ping?${new URLSearchParams({ group, service }).toString()}`, {
refreshInterval: 30000 refreshInterval: 30000,
}); });
let colorClass = "" let colorClass = "text-black/20 dark:text-white/40 opacity-20";
let backgroundClass = "bg-theme-500/10 dark:bg-theme-900/50 px-1.5 py-0.5"; let backgroundClass = "bg-theme-500/10 dark:bg-theme-900/50 px-1.5 py-0.5";
let statusTitle = "HTTP status"; let statusTitle = t("ping.http_status");
let statusText; let statusText = "";
if (error) { if (error) {
colorClass = "text-rose-500" colorClass = "text-rose-500";
statusText = t("ping.error") statusText = t("ping.error");
statusTitle += " error" statusTitle += ` ${t("ping.error")}`;
} else if (!data) { } else if (!data) {
colorClass = "text-black/20 dark:text-white/40" statusText = t("ping.ping");
statusText = t("ping.ping") statusTitle += ` ${t("ping.not_available")}`;
statusTitle += " not available"
} else if (data.status > 403) { } else if (data.status > 403) {
colorClass = "text-rose-500/80" colorClass = "text-rose-500/80";
statusTitle += ` ${data.status}` statusTitle += ` ${data.status}`;
if (style === "basic") { if (style === "basic") {
statusText = t("ping.down") statusText = t("ping.down");
} else { } else {
statusText = data.status statusText = data.status;
} }
} else { } else if (data) {
const ping = t("common.ms", { value: data.latency, style: "unit", unit: "millisecond", maximumFractionDigits: 0 }) const ping = t("common.ms", { value: data.latency, style: "unit", unit: "millisecond", maximumFractionDigits: 0 });
statusTitle += ` ${data.status} (${ping})`; statusTitle += ` ${data.status} (${ping})`;
colorClass = "text-emerald-500/80" colorClass = "text-emerald-500/80";
if (style === "basic") { if (style === "basic") {
statusText = t("ping.up") statusText = t("ping.up");
} else { } else {
statusText = ping statusText = ping;
colorClass += " lowercase" colorClass += " lowercase";
} }
} }
if (style === "dot") { if (style === "dot") {
backgroundClass = 'p-3'; backgroundClass = "p-4";
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, ''); colorClass = colorClass.replace(/text-/g, "bg-").replace(/\/\d\d/g, "");
} }
return ( return (
<div className={`w-auto text-center rounded-b-[3px] overflow-hidden ping-status ${backgroundClass}`} title={statusTitle}> <div
{style !== 'dot' && <div className={`font-bold uppercase text-[8px] ${colorClass}`}>{statusText}</div>} className={`w-auto text-center rounded-b-[3px] overflow-hidden ping-status ${backgroundClass}`}
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>} title={statusTitle}
>
{style !== "dot" && <div className={`font-bold uppercase text-[8px] ${colorClass}`}>{statusText}</div>}
{style === "dot" && <div className={`rounded-full h-3 w-3 ${colorClass}`} />}
</div> </div>
); );
} }

View File

@@ -37,22 +37,29 @@ export default function Status({ service, style }) {
} }
if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) { if (data.status === "not found" || data.status === "exited" || data.status?.startsWith("partial")) {
if (data.status === "not found") statusLabel = t("docker.not_found") if (data.status === "not found") statusLabel = t("docker.not_found");
else if (data.status === "exited") statusLabel = t("docker.exited") else if (data.status === "exited") statusLabel = t("docker.exited");
else statusLabel = data.status.replace("partial", t("docker.partial")) else statusLabel = data.status.replace("partial", t("docker.partial"));
colorClass = "text-orange-400/50 dark:text-orange-400/80"; colorClass = "text-orange-400/50 dark:text-orange-400/80";
} }
} }
if (style === 'dot') { if (style === "dot") {
colorClass = colorClass.replace('text-', 'bg-').replace(/\/\d\d$/, ''); colorClass = colorClass.replace(/text-/g, "bg-").replace(/\/\d\d/g, "");
backgroundClass = "p-3 hover:bg-theme-500/10 dark:hover:bg-theme-900/20"; backgroundClass = "p-4 hover:bg-theme-500/10 dark:hover:bg-theme-900/20";
statusTitle = statusLabel;
} }
return ( return (
<div className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] docker-status`} title={statusTitle}> <div
{style !== 'dot' && <div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>} className={`w-auto text-center overflow-hidden ${backgroundClass} rounded-b-[3px] docker-status`}
{style === 'dot' && <div className={`rounded-full h-3 w-3 ${colorClass}`}/>} title={statusTitle}
>
{style !== "dot" ? (
<div className={`text-[8px] font-bold ${colorClass} uppercase`}>{statusLabel}</div>
) : (
<div className={`rounded-full h-3 w-3 ${colorClass}`} />
)}
</div> </div>
); );
} }

View File

@@ -9,7 +9,7 @@ export default function Block({ value, label }) {
className={classNames( className={classNames(
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center p-1", "bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center p-1",
value === undefined ? "animate-pulse" : "", value === undefined ? "animate-pulse" : "",
"service-block" "service-block",
)} )}
> >
<div className="font-thin text-sm">{value === undefined || value === null ? "-" : value}</div> <div className="font-thin text-sm">{value === undefined || value === null ? "-" : value}</div>

View File

@@ -12,14 +12,14 @@ export default function Container({ error = false, children, service }) {
return null; return null;
} }
return <Error service={service} error={error} /> return <Error service={service} error={error} />;
} }
const childrenArray = Array.isArray(children) ? children : [children]; const childrenArray = Array.isArray(children) ? children : [children];
let visibleChildren = childrenArray; let visibleChildren = childrenArray;
let fields = service?.widget?.fields; let fields = service?.widget?.fields;
if (typeof fields === 'string') fields = JSON.parse(service.widget.fields); if (typeof fields === "string") fields = JSON.parse(service.widget.fields);
const type = service?.widget?.type; const type = service?.widget?.type;
if (fields && type) { if (fields && type) {
// if the field contains a "." then it most likely contains a common loc value // if the field contains a "." then it most likely contains a common loc value
@@ -27,13 +27,15 @@ export default function Container({ error = false, children, service }) {
// fields: [ "resources.cpu", "resources.mem", "field"] // fields: [ "resources.cpu", "resources.mem", "field"]
// or even // or even
// fields: [ "resources.cpu", "widget_type.field" ] // fields: [ "resources.cpu", "widget_type.field" ]
visibleChildren = childrenArray?.filter(child => fields.some(field => { visibleChildren = childrenArray?.filter((child) =>
fields.some((field) => {
let fullField = field; let fullField = field;
if (!field.includes(".")) { if (!field.includes(".")) {
fullField = `${type}.${field}`; fullField = `${type}.${field}`;
} }
return fullField === child?.props?.label; return fullField === child?.props?.label;
})); }),
);
} }
return <div className="relative flex flex-row w-full service-container">{visibleChildren}</div>; return <div className="relative flex flex-row w-full service-container">{visibleChildren}</div>;

View File

@@ -6,7 +6,7 @@ function displayError(error) {
} }
function displayData(data) { function displayData(data) {
return (data.type === 'Buffer') ? Buffer.from(data).toString() : JSON.stringify(data, 4); return data.type === "Buffer" ? Buffer.from(data).toString() : JSON.stringify(data, 4);
} }
export default function Error({ error }) { export default function Error({ error }) {
@@ -20,29 +20,34 @@ export default function Error({ error }) {
<details className="px-1 pb-1"> <details className="px-1 pb-1">
<summary className="block text-center mt-1 mb-0 mx-auto p-3 rounded bg-rose-900/80 hover:bg-rose-900/95 text-theme-900 cursor-pointer"> <summary className="block text-center mt-1 mb-0 mx-auto p-3 rounded bg-rose-900/80 hover:bg-rose-900/95 text-theme-900 cursor-pointer">
<div className="flex items-center justify-center text-xs font-bold"> <div className="flex items-center justify-center text-xs font-bold">
<IoAlertCircle className="mr-1 w-5 h-5"/>{t("widget.api_error")} {error.message && t("widget.information")} <IoAlertCircle className="mr-1 w-5 h-5" />
{t("widget.api_error")} {error.message && t("widget.information")}
</div> </div>
</summary> </summary>
<div className="bg-white dark:bg-theme-200/50 mt-2 rounded text-rose-900 text-xs font-mono whitespace-pre-wrap break-all"> <div className="bg-white dark:bg-theme-200/50 mt-2 rounded text-rose-900 text-xs font-mono whitespace-pre-wrap break-all">
<ul className="p-4"> <ul className="p-4">
{error.message && <li> {error.message && (
<li>
<span className="text-black">{t("widget.api_error")}:</span> {error.message} <span className="text-black">{t("widget.api_error")}:</span> {error.message}
</li>} </li>
{error.url && <li className="mt-2"> )}
{error.url && (
<li className="mt-2">
<span className="text-black">{t("widget.url")}:</span> {error.url} <span className="text-black">{t("widget.url")}:</span> {error.url}
</li>} </li>
{error.rawError && <li className="mt-2"> )}
{error.rawError && (
<li className="mt-2">
<span className="text-black">{t("widget.raw_error")}:</span> <span className="text-black">{t("widget.raw_error")}:</span>
<div className="ml-2"> <div className="ml-2">{displayError(error.rawError)}</div>
{displayError(error.rawError)} </li>
</div> )}
</li>} {error.data && (
{error.data && <li className="mt-2"> <li className="mt-2">
<span className="text-black">{t("widget.response_data")}:</span> <span className="text-black">{t("widget.response_data")}:</span>
<div className="ml-2"> <div className="ml-2">{displayData(error.data)}</div>
{displayData(error.data)} </li>
</div> )}
</li>}
</ul> </ul>
</div> </div>
</details> </details>

View File

@@ -4,28 +4,37 @@ import classNames from "classnames";
import { TabContext } from "utils/contexts/tab"; import { TabContext } from "utils/contexts/tab";
export function slugify(tabName) { export function slugify(tabName) {
return tabName !== undefined ? encodeURIComponent(tabName.toString().replace(/\s+/g, '-').toLowerCase()) : '' return tabName !== undefined ? encodeURIComponent(tabName.toString().replace(/\s+/g, "-").toLowerCase()) : "";
} }
export default function Tab({ tab }) { export default function Tab({ tab }) {
const { activeTab, setActiveTab } = useContext(TabContext); const { activeTab, setActiveTab } = useContext(TabContext);
return ( return (
<li key={tab} role="presentation" <li
className={classNames( key={tab}
"text-theme-700 dark:text-theme-200 relative h-8 w-full rounded-md flex m-1", role="presentation"
)}> className={classNames("text-theme-700 dark:text-theme-200 relative h-8 w-full rounded-md flex m-1")}
<button id={`${tab}-tab`} type="button" role="tab" >
aria-controls={`#${tab}`} aria-selected={activeTab === slugify(tab) ? "true" : "false"} <button
id={`${tab}-tab`}
type="button"
role="tab"
aria-controls={`#${tab}`}
aria-selected={activeTab === slugify(tab) ? "true" : "false"}
className={classNames( className={classNames(
"h-full w-full rounded-md", "h-full w-full rounded-md",
activeTab === slugify(tab) ? "bg-theme-300/20 dark:bg-white/10" : "hover:bg-theme-100/20 dark:hover:bg-white/5", activeTab === slugify(tab)
? "bg-theme-300/20 dark:bg-white/10"
: "hover:bg-theme-100/20 dark:hover:bg-white/5",
)} )}
onClick={() => { onClick={() => {
setActiveTab(slugify(tab)); setActiveTab(slugify(tab));
window.location.hash = `#${slugify(tab)}`; window.location.hash = `#${slugify(tab)}`;
}} }}
>{tab}</button> >
{tab}
</button>
</li> </li>
); );
} }

View File

@@ -65,7 +65,7 @@ export default function ColorToggle() {
title={color} title={color}
className={classNames( className={classNames(
active === color ? "border-2" : "border-0", active === color ? "border-2" : "border-0",
`rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-400` `rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-400`,
)} )}
/> />
<span className="sr-only">{color}</span> <span className="sr-only">{color}</span>

View File

@@ -6,7 +6,9 @@ import { MdNewReleases } from "react-icons/md";
export default function Version() { export default function Version() {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const buildTime = process.env.NEXT_PUBLIC_BUILDTIME?.length ? process.env.NEXT_PUBLIC_BUILDTIME : new Date().toISOString(); const buildTime = process.env.NEXT_PUBLIC_BUILDTIME?.length
? process.env.NEXT_PUBLIC_BUILDTIME
: new Date().toISOString();
const revision = process.env.NEXT_PUBLIC_REVISION?.length ? process.env.NEXT_PUBLIC_REVISION : "dev"; const revision = process.env.NEXT_PUBLIC_REVISION?.length ? process.env.NEXT_PUBLIC_REVISION : "dev";
const version = process.env.NEXT_PUBLIC_VERSION?.length ? process.env.NEXT_PUBLIC_VERSION : "dev"; const version = process.env.NEXT_PUBLIC_VERSION?.length ? process.env.NEXT_PUBLIC_VERSION : "dev";
@@ -44,7 +46,8 @@ export default function Version() {
</span> </span>
{version === "main" || version === "dev" || version === "nightly" {version === "main" || version === "dev" || version === "nightly"
? null ? null
: releaseData && latestRelease && : releaseData &&
latestRelease &&
compareVersions(latestRelease.tag_name, version) > 0 && ( compareVersions(latestRelease.tag_name, version) > 0 && (
<a <a
href={latestRelease.html_url} href={latestRelease.html_url}

View File

@@ -15,7 +15,7 @@ import { SettingsContext } from "utils/contexts/settings";
const cpuSensorLabels = ["cpu_thermal", "Core", "Tctl"]; const cpuSensorLabels = ["cpu_thermal", "Core", "Tctl"];
function convertToFahrenheit(t) { function convertToFahrenheit(t) {
return t * 9/5 + 32 return (t * 9) / 5 + 32;
} }
export default function Widget({ options }) { export default function Widget({ options }) {
@@ -23,35 +23,49 @@ export default function Widget({ options }) {
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
const { data, error } = useSWR( const { data, error } = useSWR(
`/api/widgets/glances?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}`, { `/api/widgets/glances?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}`,
{
refreshInterval: 1500, refreshInterval: 1500,
} },
); );
if (error || data?.error) { if (error || data?.error) {
return <Error options={options} /> return <Error options={options} />;
} }
if (!data) { if (!data) {
return <Resources options={options} additionalClassNames="information-widget-glances"> return (
<Resources options={options} additionalClassNames="information-widget-glances">
{options.cpu !== false && <Resource icon={FiCpu} label={t("glances.wait")} percentage="0" />} {options.cpu !== false && <Resource icon={FiCpu} label={t("glances.wait")} percentage="0" />}
{options.mem !== false && <Resource icon={FaMemory} label={t("glances.wait")} percentage="0" />} {options.mem !== false && <Resource icon={FaMemory} label={t("glances.wait")} percentage="0" />}
{options.cputemp && <Resource icon={FaThermometerHalf} label={t("glances.wait")} percentage="0" />} {options.cputemp && <Resource icon={FaThermometerHalf} label={t("glances.wait")} percentage="0" />}
{ options.disk && !Array.isArray(options.disk) && <Resource key={options.disk} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> } {options.disk && !Array.isArray(options.disk) && (
{ options.disk && Array.isArray(options.disk) && options.disk.map((disk) => <Resource key={`disk_${disk}`} icon={FiHardDrive} label={t("glances.wait")} percentage="0" /> ) } <Resource key={options.disk} icon={FiHardDrive} label={t("glances.wait")} percentage="0" />
)}
{options.disk &&
Array.isArray(options.disk) &&
options.disk.map((disk) => (
<Resource key={`disk_${disk}`} icon={FiHardDrive} label={t("glances.wait")} percentage="0" />
))}
{options.uptime && <Resource icon={FaRegClock} label={t("glances.wait")} percentage="0" />} {options.uptime && <Resource icon={FaRegClock} label={t("glances.wait")} percentage="0" />}
{options.label && <WidgetLabel label={options.label} />} {options.label && <WidgetLabel label={options.label} />}
</Resources>; </Resources>
);
} }
const unit = options.units === "imperial" ? "fahrenheit" : "celsius"; const unit = options.units === "imperial" ? "fahrenheit" : "celsius";
let mainTemp = 0; let mainTemp = 0;
let maxTemp = 80; let maxTemp = 80;
const cpuSensors = data.sensors?.filter(s => cpuSensorLabels.some(label => s.label.startsWith(label)) && s.type === "temperature_core"); const cpuSensors = data.sensors?.filter(
(s) => cpuSensorLabels.some((label) => s.label.startsWith(label)) && s.type === "temperature_core",
);
if (options.cputemp && cpuSensors) { if (options.cputemp && cpuSensors) {
try { try {
mainTemp = cpuSensors.reduce((acc, s) => acc + s.value, 0) / cpuSensors.length; mainTemp = cpuSensors.reduce((acc, s) => acc + s.value, 0) / cpuSensors.length;
maxTemp = Math.max(cpuSensors.reduce((acc, s) => acc + (s.warning > 0 ? s.warning : 0), 0) / cpuSensors.length, maxTemp); maxTemp = Math.max(
cpuSensors.reduce((acc, s) => acc + (s.warning > 0 ? s.warning : 0), 0) / cpuSensors.length,
maxTemp,
);
if (unit === "fahrenheit") { if (unit === "fahrenheit") {
mainTemp = convertToFahrenheit(mainTemp); mainTemp = convertToFahrenheit(mainTemp);
maxTemp = convertToFahrenheit(maxTemp); maxTemp = convertToFahrenheit(maxTemp);
@@ -70,11 +84,12 @@ export default function Widget({ options }) {
: [data.fs.find((d) => d.mnt_point === options.disk)].filter((d) => d); : [data.fs.find((d) => d.mnt_point === options.disk)].filter((d) => d);
} }
const addedClasses = classNames('information-widget-glances', { 'expanded': options.expanded }) const addedClasses = classNames("information-widget-glances", { expanded: options.expanded });
return ( return (
<Resources options={options} target={settings.target ?? "_blank"} additionalClassNames={addedClasses}> <Resources options={options} target={settings.target ?? "_blank"} additionalClassNames={addedClasses}>
{options.cpu !== false && <Resource {options.cpu !== false && (
<Resource
icon={FiCpu} icon={FiCpu}
value={t("common.number", { value={t("common.number", {
value: data.cpu.total, value: data.cpu.total,
@@ -87,13 +102,15 @@ export default function Widget({ options }) {
value: data.load.min15, value: data.load.min15,
style: "unit", style: "unit",
unit: "percent", unit: "percent",
maximumFractionDigits: 0 maximumFractionDigits: 0,
})} })}
expandedLabel={t("glances.load")} expandedLabel={t("glances.load")}
percentage={data.cpu.total} percentage={data.cpu.total}
expanded={options.expanded} expanded={options.expanded}
/>} />
{options.mem !== false && <Resource )}
{options.mem !== false && (
<Resource
icon={FaMemory} icon={FaMemory}
value={t("common.bytes", { value={t("common.bytes", {
value: data.mem.free, value: data.mem.free,
@@ -109,9 +126,11 @@ export default function Widget({ options }) {
expandedLabel={t("glances.total")} expandedLabel={t("glances.total")}
percentage={data.mem.percent} percentage={data.mem.percent}
expanded={options.expanded} expanded={options.expanded}
/>} />
)}
{disks.map((disk) => ( {disks.map((disk) => (
<Resource key={`disk_${disk.mnt_point ?? disk.device_name}`} <Resource
key={`disk_${disk.mnt_point ?? disk.device_name}`}
icon={FiHardDrive} icon={FiHardDrive}
value={t("common.bytes", { value: disk.free })} value={t("common.bytes", { value: disk.free })}
label={t("glances.free")} label={t("glances.free")}
@@ -121,35 +140,35 @@ export default function Widget({ options }) {
expanded={options.expanded} expanded={options.expanded}
/> />
))} ))}
{options.cputemp && mainTemp > 0 && {options.cputemp && mainTemp > 0 && (
<Resource <Resource
icon={FaThermometerHalf} icon={FaThermometerHalf}
value={t("common.number", { value={t("common.number", {
value: mainTemp, value: mainTemp,
maximumFractionDigits: 1, maximumFractionDigits: 1,
style: "unit", style: "unit",
unit unit,
})} })}
label={t("glances.temp")} label={t("glances.temp")}
expandedValue={t("common.number", { expandedValue={t("common.number", {
value: maxTemp, value: maxTemp,
maximumFractionDigits: 1, maximumFractionDigits: 1,
style: "unit", style: "unit",
unit unit,
})} })}
expandedLabel={t("glances.warn")} expandedLabel={t("glances.warn")}
percentage={tempPercent} percentage={tempPercent}
expanded={options.expanded} expanded={options.expanded}
/> />
} )}
{options.uptime && data.uptime && {options.uptime && data.uptime && (
<Resource <Resource
icon={FaRegClock} icon={FaRegClock}
value={data.uptime.replace(" days,", t("glances.days")).replace(/:\d\d:\d\d$/g, t("glances.hours"))} value={data.uptime.replace(" days,", t("glances.days")).replace(/:\d\d:\d\d$/g, t("glances.hours"))}
label={t("glances.uptime")} label={t("glances.uptime")}
percentage={Math.round((new Date().getSeconds() / 60) * 100).toString()} percentage={Math.round((new Date().getSeconds() / 60) * 100).toString()}
/> />
} )}
{options.label && <WidgetLabel label={options.label} />} {options.label && <WidgetLabel label={options.label} />}
</Resources> </Resources>
); );

View File

@@ -14,12 +14,14 @@ const textSizes = {
export default function Greeting({ options }) { export default function Greeting({ options }) {
if (options.text) { if (options.text) {
return <Container options={options} additionalClassNames="information-widget-greeting"> return (
<Container options={options} additionalClassNames="information-widget-greeting">
<Raw> <Raw>
<span className={`text-theme-800 dark:text-theme-200 mr-3 ${textSizes[options.text_size || "xl"]}`}> <span className={`text-theme-800 dark:text-theme-200 mr-3 ${textSizes[options.text_size || "xl"]}`}>
{options.text} {options.text}
</span> </span>
</Raw> </Raw>
</Container>; </Container>
);
} }
} }

View File

@@ -15,52 +15,47 @@ export default function Widget({ options }) {
cpu: { cpu: {
load: 0, load: 0,
total: 0, total: 0,
percent: 0 percent: 0,
}, },
memory: { memory: {
used: 0, used: 0,
total: 0, total: 0,
free: 0, free: 0,
percent: 0 percent: 0,
} },
}; };
const { data, error } = useSWR( const { data, error } = useSWR(`/api/widgets/kubernetes?${new URLSearchParams({ lang: i18n.language }).toString()}`, {
`/api/widgets/kubernetes?${new URLSearchParams({ lang: i18n.language }).toString()}`, { refreshInterval: 1500,
refreshInterval: 1500 });
}
);
if (error || data?.error) { if (error || data?.error) {
return <Error options={options} /> return <Error options={options} />;
} }
if (!data) { if (!data) {
return <Container options={options} additionalClassNames="information-widget-kubernetes"> return (
<Container options={options} additionalClassNames="information-widget-kubernetes">
<Raw> <Raw>
<div className="flex flex-row self-center flex-wrap justify-between"> <div className="flex flex-row self-center flex-wrap justify-between">
{cluster.show && {cluster.show && <Node type="cluster" key="cluster" options={options.cluster} data={defaultData} />}
<Node type="cluster" key="cluster" options={options.cluster} data={defaultData} /> {nodes.show && <Node type="node" key="nodes" options={options.nodes} data={defaultData} />}
}
{nodes.show &&
<Node type="node" key="nodes" options={options.nodes} data={defaultData} />
}
</div> </div>
</Raw> </Raw>
</Container>; </Container>
);
} }
return <Container options={options} additionalClassNames="information-widget-kubernetes"> return (
<Container options={options} additionalClassNames="information-widget-kubernetes">
<Raw> <Raw>
<div className="flex flex-row self-center flex-wrap justify-between"> <div className="flex flex-row self-center flex-wrap justify-between">
{cluster.show && {cluster.show && <Node key="cluster" type="cluster" options={options.cluster} data={data.cluster} />}
<Node key="cluster" type="cluster" options={options.cluster} data={data.cluster} /> {nodes.show &&
} data.nodes &&
{nodes.show && data.nodes && data.nodes.map((node) => <Node key={node.name} type="node" options={options.nodes} data={node} />)}
data.nodes.map((node) =>
<Node key={node.name} type="node" options={options.nodes} data={node} />)
}
</div> </div>
</Raw> </Raw>
</Container>; </Container>
);
} }

View File

@@ -8,7 +8,6 @@ import UsageBar from "../resources/usage-bar";
export default function Node({ type, options, data }) { export default function Node({ type, options, data }) {
const { t } = useTranslation(); const { t } = useTranslation();
function icon() { function icon() {
if (type === "cluster") { if (type === "cluster") {
return <SiKubernetes className="text-theme-800 dark:text-theme-200 w-5 h-5" />; return <SiKubernetes className="text-theme-800 dark:text-theme-200 w-5 h-5" />;
@@ -31,7 +30,7 @@ export default function Node({ type, options, data }) {
value: data?.cpu?.percent ?? 0, value: data?.cpu?.percent ?? 0,
style: "unit", style: "unit",
unit: "percent", unit: "percent",
maximumFractionDigits: 0 maximumFractionDigits: 0,
})} })}
</div> </div>
<FiCpu className="text-theme-800 dark:text-theme-200 w-3 h-3" /> <FiCpu className="text-theme-800 dark:text-theme-200 w-3 h-3" />
@@ -42,14 +41,16 @@ export default function Node({ type, options, data }) {
{t("common.bytes", { {t("common.bytes", {
value: data?.memory?.free ?? 0, value: data?.memory?.free ?? 0,
maximumFractionDigits: 0, maximumFractionDigits: 0,
binary: true binary: true,
})} })}
</div> </div>
<FaMemory className="text-theme-800 dark:text-theme-200 w-3 h-3" /> <FaMemory className="text-theme-800 dark:text-theme-200 w-3 h-3" />
</div> </div>
<UsageBar percent={data?.memory?.percent} /> <UsageBar percent={data?.memory?.percent} />
{options.showLabel && ( {options.showLabel && (
<div className="pt-1 text-center text-theme-800 dark:text-theme-200 text-xs">{type === "cluster" ? options.label : data.name}</div> <div className="pt-1 text-center text-theme-800 dark:text-theme-200 text-xs">
{type === "cluster" ? options.label : data.name}
</div>
)} )}
</div> </div>
</div> </div>

View File

@@ -1,16 +1,20 @@
import Container from "../widget/container"; import Container from "../widget/container";
import Raw from "../widget/raw"; import Raw from "../widget/raw";
import ResolvedIcon from "components/resolvedicon" import ResolvedIcon from "components/resolvedicon";
export default function Logo({ options }) { export default function Logo({ options }) {
return ( return (
<Container options={options} additionalClassNames={`information-widget-logo ${ options.icon ? 'resolved' : 'fallback'}`}> <Container
options={options}
additionalClassNames={`information-widget-logo ${options.icon ? "resolved" : "fallback"}`}
>
<Raw> <Raw>
{options.icon ? {options.icon ? (
<div className="resolved mr-3"> <div className="resolved mr-3">
<ResolvedIcon icon={options.icon} width={48} height={48} /> <ResolvedIcon icon={options.icon} width={48} height={48} />
</div> : </div>
) : (
// fallback to homepage logo // fallback to homepage logo
<div className="fallback w-12 h-12"> <div className="fallback w-12 h-12">
<svg <svg
@@ -64,8 +68,8 @@ export default function Logo({ options }) {
</g> </g>
</svg> </svg>
</div> </div>
} )}
</Raw> </Raw>
</Container> </Container>
) );
} }

View File

@@ -9,27 +9,30 @@ import Node from "./node";
export default function Longhorn({ options }) { export default function Longhorn({ options }) {
const { expanded, total, labels, include, nodes } = options; const { expanded, total, labels, include, nodes } = options;
const { data, error } = useSWR(`/api/widgets/longhorn`, { const { data, error } = useSWR(`/api/widgets/longhorn`, {
refreshInterval: 1500 refreshInterval: 1500,
}); });
if (error || data?.error) { if (error || data?.error) {
return <Error options={options} /> return <Error options={options} />;
} }
if (!data) { if (!data) {
return <Container options={options} additionalClassNames="infomation-widget-longhorn"> return (
<Container options={options} additionalClassNames="infomation-widget-longhorn">
<Raw> <Raw>
<div className="flex flex-row self-center flex-wrap justify-between" /> <div className="flex flex-row self-center flex-wrap justify-between" />
</Raw> </Raw>
</Container>; </Container>
);
} }
return <Container options={options} additionalClassNames="infomation-widget-longhorn"> return (
<Container options={options} additionalClassNames="infomation-widget-longhorn">
<Raw> <Raw>
<div className="flex flex-row self-center flex-wrap justify-between"> <div className="flex flex-row self-center flex-wrap justify-between">
{data.nodes {data.nodes
.filter((node) => { .filter((node) => {
if (node.id === 'total' && total) { if (node.id === "total" && total) {
return true; return true;
} }
if (!nodes) { if (!nodes) {
@@ -40,12 +43,13 @@ export default function Longhorn({ options }) {
} }
return true; return true;
}) })
.map((node) => .map((node) => (
<div key={node.id}> <div key={node.id}>
<Node data={{ node }} expanded={expanded} labels={labels} /> <Node data={{ node }} expanded={expanded} labels={labels} />
</div> </div>
)} ))}
</div> </div>
</Raw> </Raw>
</Container>; </Container>
);
} }

Some files were not shown because too many files have changed in this diff Show More