mirror of
https://github.com/gethomepage/homepage.git
synced 2025-12-05 21:47:48 +01:00
Compare commits
437 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5ac34a6b5 | ||
|
|
015d7dac52 | ||
|
|
c3d15a61c3 | ||
|
|
f517d704b8 | ||
|
|
167f3a4f84 | ||
|
|
e411e2ac0d | ||
|
|
ff27b1ef51 | ||
|
|
41a2e5932f | ||
|
|
fb1e11b6cb | ||
|
|
dfc787b004 | ||
|
|
224d5da982 | ||
|
|
713344132a | ||
|
|
49d2dabe53 | ||
|
|
147a165bbc | ||
|
|
046f2986a8 | ||
|
|
ad299e9c94 | ||
|
|
7a5a3a6608 | ||
|
|
87dbbcb1e0 | ||
|
|
3bc0522812 | ||
|
|
adea9da881 | ||
|
|
1ccf0b3c7a | ||
|
|
3c44e49b76 | ||
|
|
711eedfc84 | ||
|
|
348833e682 | ||
|
|
fe128a976f | ||
|
|
7ca1839287 | ||
|
|
7ac98d010c | ||
|
|
4af1f1bb7d | ||
|
|
69a86bc5dc | ||
|
|
98ca15c962 | ||
|
|
4837f26aa1 | ||
|
|
3c06637dd7 | ||
|
|
076c2fbb0d | ||
|
|
3034b78772 | ||
|
|
bddbe890f8 | ||
|
|
f7520f2fdf | ||
|
|
158dcf0098 | ||
|
|
6e5efc6804 | ||
|
|
329985927b | ||
|
|
c648e106db | ||
|
|
2356745e15 | ||
|
|
c52bc57190 | ||
|
|
2e43b93eb6 | ||
|
|
6d779355b3 | ||
|
|
10fb1be641 | ||
|
|
10a4cb8552 | ||
|
|
2951574caa | ||
|
|
4e0a1fdcdd | ||
|
|
d38948bb6a | ||
|
|
53743119b8 | ||
|
|
38d1ecc7c0 | ||
|
|
b31e64d1dc | ||
|
|
8f5dcd5175 | ||
|
|
1f5912c232 | ||
|
|
9b8e01971f | ||
|
|
7b12c9e24a | ||
|
|
e079587d89 | ||
|
|
6a0a5ff1f7 | ||
|
|
e3e5c0274b | ||
|
|
de70ce620e | ||
|
|
56d9ec64fd | ||
|
|
bca597febe | ||
|
|
579cac73e0 | ||
|
|
c29b174dcf | ||
|
|
c693a5e690 | ||
|
|
e4724690b2 | ||
|
|
eb679d615b | ||
|
|
a9e70b815d | ||
|
|
96b00f9207 | ||
|
|
fb5ebb0ca0 | ||
|
|
9550071dab | ||
|
|
4581833ed4 | ||
|
|
fe148d4cd0 | ||
|
|
9076de919b | ||
|
|
5cf95eb383 | ||
|
|
1785206df0 | ||
|
|
1805b43816 | ||
|
|
f406af59bc | ||
|
|
98b4280a02 | ||
|
|
9699481b9a | ||
|
|
ab436152dd | ||
|
|
cacbe6d17b | ||
|
|
50b435b7e3 | ||
|
|
4e47b19fb9 | ||
|
|
66620c5d42 | ||
|
|
f1aa9444c1 | ||
|
|
908ee43375 | ||
|
|
c2e52f8821 | ||
|
|
3194e5af85 | ||
|
|
2fae3243a7 | ||
|
|
adce18d023 | ||
|
|
11d03be4de | ||
|
|
4e17628f97 | ||
|
|
cf072933a1 | ||
|
|
f8a57b1a5f | ||
|
|
385e935533 | ||
|
|
eaa7f1bf6d | ||
|
|
fb7ad30dfc | ||
|
|
95fcd821be | ||
|
|
a4e1083d02 | ||
|
|
7e9ed86441 | ||
|
|
c76d750e18 | ||
|
|
b75617e2f2 | ||
|
|
cf7ba59f0f | ||
|
|
14377962f2 | ||
|
|
aab38e1b5f | ||
|
|
1449c5a0a3 | ||
|
|
72481876f8 | ||
|
|
7f207692ce | ||
|
|
dab31b2feb | ||
|
|
13d2213ceb | ||
|
|
2a77bb11c5 | ||
|
|
fcf9c6417b | ||
|
|
e08ce475f5 | ||
|
|
ba96ab8b50 | ||
|
|
0743095093 | ||
|
|
0bb40d7ad1 | ||
|
|
33467a5c63 | ||
|
|
f88de790a9 | ||
|
|
85afbcb86c | ||
|
|
c502f65d07 | ||
|
|
6baf028d6d | ||
|
|
8441838065 | ||
|
|
901be4ff60 | ||
|
|
c9e8b13c37 | ||
|
|
ac1a3e95ca | ||
|
|
9978bf6fdc | ||
|
|
7f5996cb58 | ||
|
|
8468ffb243 | ||
|
|
a7927b4873 | ||
|
|
c9439eafa2 | ||
|
|
5af01d2436 | ||
|
|
19cf9969b9 | ||
|
|
dbcd6f5df7 | ||
|
|
6b5e8ab0c7 | ||
|
|
e5d65f410c | ||
|
|
f2b3a12569 | ||
|
|
3df03ecaab | ||
|
|
0fdab8cffc | ||
|
|
7d23b0199c | ||
|
|
0ae6d7e182 | ||
|
|
2b8af9546f | ||
|
|
8713ef4d6a | ||
|
|
0d5c878c29 | ||
|
|
bb823140e1 | ||
|
|
749e78864e | ||
|
|
6199c2e3b0 | ||
|
|
935681bd70 | ||
|
|
dc7f563fff | ||
|
|
8c3b8e2cbc | ||
|
|
60df0ab4ff | ||
|
|
436650d8ef | ||
|
|
6e6fcb33ce | ||
|
|
ba25e74add | ||
|
|
59c524726a | ||
|
|
7e3620f86f | ||
|
|
b11fa21d4a | ||
|
|
3fdae79c88 | ||
|
|
933619aa8e | ||
|
|
63616e0a79 | ||
|
|
c933e40e92 | ||
|
|
347e28ea3f | ||
|
|
f6fdbd0426 | ||
|
|
5d82f5f7d8 | ||
|
|
4c9f1041ef | ||
|
|
6d133b3889 | ||
|
|
d94f1ce3e7 | ||
|
|
1e8b257dbe | ||
|
|
0190c18a6b | ||
|
|
56331b3efd | ||
|
|
c3561e8fce | ||
|
|
910582fbc0 | ||
|
|
2a42d89d08 | ||
|
|
b0f16f6612 | ||
|
|
0d5f8f6e7c | ||
|
|
e368717c70 | ||
|
|
1e5a6f8eff | ||
|
|
945d13ee3c | ||
|
|
cc09e44890 | ||
|
|
29b6fefdff | ||
|
|
e96036e076 | ||
|
|
8d016629d3 | ||
|
|
555f9f7b14 | ||
|
|
02e9df8f28 | ||
|
|
5ecb9466ae | ||
|
|
9c9c0e2b64 | ||
|
|
2d87c7c1d2 | ||
|
|
cdbf02edae | ||
|
|
b630b14504 | ||
|
|
e0bf277741 | ||
|
|
351993234e | ||
|
|
192a4f4d14 | ||
|
|
bfb882d03d | ||
|
|
9ee86f1c5a | ||
|
|
6d3c71a72e | ||
|
|
ad273ce5ad | ||
|
|
799c9ecb17 | ||
|
|
a5c8f08f4b | ||
|
|
9f2476f419 | ||
|
|
942a61aa4b | ||
|
|
099f3726e8 | ||
|
|
14310bf2ed | ||
|
|
176811da9b | ||
|
|
f8d35e7f5d | ||
|
|
ce94636a54 | ||
|
|
7e659b2dbc | ||
|
|
cb92e82fd0 | ||
|
|
d7d5f46820 | ||
|
|
23b8f25f07 | ||
|
|
dc55da38c6 | ||
|
|
aa35eb5c5e | ||
|
|
8c800eb032 | ||
|
|
cdfb7e7d73 | ||
|
|
48298cc4e8 | ||
|
|
ce786fb765 | ||
|
|
50939069af | ||
|
|
ec8a73751c | ||
|
|
a994d5379e | ||
|
|
f9e27a6bb5 | ||
|
|
6d61cb5aaa | ||
|
|
89c6528f24 | ||
|
|
2836ee1f3b | ||
|
|
d71a1f9345 | ||
|
|
c8116fc9e8 | ||
|
|
ca4b5b131d | ||
|
|
c74b46712b | ||
|
|
794f22d373 | ||
|
|
fa1792cd5f | ||
|
|
cdbdb86c9e | ||
|
|
71669b295d | ||
|
|
9f68f3b3f4 | ||
|
|
0b41c1d686 | ||
|
|
85073629ad | ||
|
|
680d889228 | ||
|
|
e4c2eec7ee | ||
|
|
0642999826 | ||
|
|
1a1194acf8 | ||
|
|
e6f9d6fd1d | ||
|
|
ec4dcd0663 | ||
|
|
1993a1660a | ||
|
|
530495d804 | ||
|
|
c490d2467f | ||
|
|
c7771033c6 | ||
|
|
ccb227366d | ||
|
|
0d4b4ef65c | ||
|
|
45b59cd336 | ||
|
|
8dcc25f68f | ||
|
|
f0557d0a9c | ||
|
|
f1baafe9a1 | ||
|
|
940b6098d4 | ||
|
|
580c6adfb1 | ||
|
|
c9cb975265 | ||
|
|
3f887a7e26 | ||
|
|
3d5bb9d9eb | ||
|
|
6cd9d76892 | ||
|
|
cc073ea23c | ||
|
|
b6a2421a64 | ||
|
|
300fce5f17 | ||
|
|
19e654656f | ||
|
|
3add3a57d2 | ||
|
|
e850abbaec | ||
|
|
d4b3885139 | ||
|
|
3737ce704e | ||
|
|
43d781f1f9 | ||
|
|
fc01c6b428 | ||
|
|
592848f42f | ||
|
|
6634909f5b | ||
|
|
6c5f27cd87 | ||
|
|
995ebb1941 | ||
|
|
d27b795d81 | ||
|
|
01eea51555 | ||
|
|
67e72fb96a | ||
|
|
c7e4a52b99 | ||
|
|
627ce179ef | ||
|
|
1ee2356028 | ||
|
|
335e2fcb1f | ||
|
|
a71fe3796f | ||
|
|
ab8114ee4f | ||
|
|
be4ed7481a | ||
|
|
4ee85bc108 | ||
|
|
a88a5aa922 | ||
|
|
87e82f5339 | ||
|
|
c741fee788 | ||
|
|
98ecb192fd | ||
|
|
ba34bb5aba | ||
|
|
1f9f9070a9 | ||
|
|
a86fa90a58 | ||
|
|
388bc74464 | ||
|
|
dd66f51105 | ||
|
|
e126a04a35 | ||
|
|
83ec439513 | ||
|
|
8afcb4e427 | ||
|
|
e84ea3a89d | ||
|
|
b80bda077d | ||
|
|
e1247a40a7 | ||
|
|
238835c625 | ||
|
|
8b229c0096 | ||
|
|
41290cf909 | ||
|
|
96ec29efd9 | ||
|
|
9c6a71c463 | ||
|
|
f7f4033e21 | ||
|
|
af3f65a648 | ||
|
|
b73d36fbd4 | ||
|
|
23a2c43e50 | ||
|
|
fe7d7a9feb | ||
|
|
ce8cef99e8 | ||
|
|
60958cad5f | ||
|
|
76701c245c | ||
|
|
2053ce7361 | ||
|
|
1935965095 | ||
|
|
006fb80533 | ||
|
|
ab2c3c6412 | ||
|
|
2c3947ea3f | ||
|
|
725189a7b0 | ||
|
|
7b61ca81bc | ||
|
|
f2d737b156 | ||
|
|
b6bee279d4 | ||
|
|
365783204a | ||
|
|
047f7af99a | ||
|
|
a880cdbc68 | ||
|
|
9f008fc04e | ||
|
|
aa8c41e715 | ||
|
|
2a5442940f | ||
|
|
3317cd8b5b | ||
|
|
d9241e03bb | ||
|
|
8e191d4103 | ||
|
|
d882e43603 | ||
|
|
4edd0edc3d | ||
|
|
9043e4d648 | ||
|
|
fb3f1d61cc | ||
|
|
4b21740e64 | ||
|
|
ef5a063af3 | ||
|
|
5aa29aafb7 | ||
|
|
d7be68e040 | ||
|
|
3d96b508d5 | ||
|
|
6c13e65802 | ||
|
|
fe9c355af5 | ||
|
|
ef7afb2589 | ||
|
|
0e19765e8b | ||
|
|
857fec1d47 | ||
|
|
a8287cb20f | ||
|
|
2507848575 | ||
|
|
fdd66c1435 | ||
|
|
827679ced6 | ||
|
|
e112b3f737 | ||
|
|
8598f4c315 | ||
|
|
8329aabe74 | ||
|
|
667519f81e | ||
|
|
ea9fa2b9c2 | ||
|
|
df3bac842e | ||
|
|
32e7323b45 | ||
|
|
62e1cfea59 | ||
|
|
92b3433e1d | ||
|
|
8723b1f101 | ||
|
|
88d2ce7d6f | ||
|
|
f65884183d | ||
|
|
fa1f51d42c | ||
|
|
578de2c52e | ||
|
|
12e111b76c | ||
|
|
82a6553c58 | ||
|
|
2a24277757 | ||
|
|
e20a0e90b2 | ||
|
|
b3e976860a | ||
|
|
1a9acd753c | ||
|
|
7f7e083a41 | ||
|
|
3aec4e6da4 | ||
|
|
59bec6e65e | ||
|
|
93dda99aaa | ||
|
|
16c419f816 | ||
|
|
a8e506504a | ||
|
|
bf5b82445f | ||
|
|
a58eebb448 | ||
|
|
233391fc4a | ||
|
|
7a4ac9ddd9 | ||
|
|
9de4bfc6fe | ||
|
|
c981a737a6 | ||
|
|
5a6b65aeb0 | ||
|
|
fa325b2497 | ||
|
|
f355464aae | ||
|
|
893b709f8b | ||
|
|
a4d1589493 | ||
|
|
4060fdc902 | ||
|
|
54f263da15 | ||
|
|
2a777e55d9 | ||
|
|
e1d6d46420 | ||
|
|
ed8e7aa01d | ||
|
|
56618ead39 | ||
|
|
1549bc67be | ||
|
|
a7f9dad6df | ||
|
|
5d6e078c87 | ||
|
|
6100cdba93 | ||
|
|
e04594defb | ||
|
|
5bc475b9df | ||
|
|
d27262c934 | ||
|
|
20e4449fd5 | ||
|
|
f3698aaeb5 | ||
|
|
7fec2af8e3 | ||
|
|
dc01dbd649 | ||
|
|
5e44ac2448 | ||
|
|
113bbc3ef1 | ||
|
|
294b27ab71 | ||
|
|
a444945faa | ||
|
|
0febf05d8d | ||
|
|
03294b5a2f | ||
|
|
a04c7677e4 | ||
|
|
67f63219f4 | ||
|
|
9634a89c81 | ||
|
|
f36c0710d8 | ||
|
|
b724f520cd | ||
|
|
a7f290dfdd | ||
|
|
98ce0e8c2e | ||
|
|
b6e8b64a2e | ||
|
|
4d6ce1f7e2 | ||
|
|
cf38395100 | ||
|
|
fc2e17fa59 | ||
|
|
642f21e56b | ||
|
|
9a072cddde | ||
|
|
36ed1022e3 | ||
|
|
e15ba1c82c | ||
|
|
7ac862be75 | ||
|
|
51ff424d98 | ||
|
|
ec08535204 | ||
|
|
a146c13c4f | ||
|
|
8543118607 | ||
|
|
27d067dc4c | ||
|
|
09eb172079 | ||
|
|
174cb651b4 | ||
|
|
c01b60dbd1 | ||
|
|
c54374068d | ||
|
|
a1f2003a77 | ||
|
|
1ca61114ef | ||
|
|
fdb143304f | ||
|
|
056e26dfd3 | ||
|
|
0c6f7dbee1 | ||
|
|
4fc6db49ca | ||
|
|
8887fcc3ee | ||
|
|
c4333fd2dc |
@@ -20,5 +20,7 @@
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
**/.next
|
||||
README.md
|
||||
config/
|
||||
k3d/
|
||||
|
||||
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@@ -88,7 +88,7 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
32
Dockerfile
32
Dockerfile
@@ -7,12 +7,10 @@ WORKDIR /app
|
||||
|
||||
COPY --link package.json pnpm-lock.yaml* ./
|
||||
|
||||
RUN <<EOF
|
||||
set -xe
|
||||
apk add libc6-compat
|
||||
apk add --virtual .gyp python3 make g++
|
||||
npm install -g pnpm
|
||||
EOF
|
||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||
RUN apk add --no-cache libc6-compat \
|
||||
&& apk add --no-cache --virtual .gyp python3 make g++ \
|
||||
&& npm install -g pnpm
|
||||
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store"
|
||||
|
||||
@@ -29,12 +27,10 @@ ARG REVISION
|
||||
COPY --link --from=deps /app/node_modules ./node_modules/
|
||||
COPY . .
|
||||
|
||||
RUN <<EOF
|
||||
set -xe
|
||||
npm run telemetry
|
||||
mkdir config && echo '-' > config/settings.yaml
|
||||
NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
||||
EOF
|
||||
SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
|
||||
RUN npm run telemetry \
|
||||
&& mkdir config && echo '---' > config/settings.yaml \
|
||||
&& NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM docker.io/node:18-alpine AS runner
|
||||
@@ -50,12 +46,15 @@ ENV NODE_ENV production
|
||||
WORKDIR /app
|
||||
|
||||
# Copy files from context (this allows the files to copy before the builder stage is done).
|
||||
COPY --link package.json next.config.js ./
|
||||
COPY --link /public ./public
|
||||
COPY --link --chown=1000:1000 package.json next.config.js ./
|
||||
COPY --link --chown=1000:1000 /public ./public/
|
||||
|
||||
# Copy files from builder
|
||||
COPY --link --from=builder /app/.next/standalone ./
|
||||
COPY --link --from=builder /app/.next/static/ ./.next/static/
|
||||
COPY --link --from=builder --chown=1000:1000 /app/.next/standalone ./
|
||||
COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static/
|
||||
COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
|
||||
|
||||
RUN apk add --no-cache su-exec
|
||||
|
||||
ENV PORT 3000
|
||||
EXPOSE $PORT
|
||||
@@ -63,4 +62,5 @@ EXPOSE $PORT
|
||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
|
||||
CMD wget --no-verbose --tries=1 --spider --no-check-certificate http://localhost:$PORT/api/healthcheck || exit 1
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["node", "server.js"]
|
||||
|
||||
22
Dockerfile-tilt
Normal file
22
Dockerfile-tilt
Normal file
@@ -0,0 +1,22 @@
|
||||
# syntax = docker/dockerfile:latest
|
||||
FROM docker.io/node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --link package.json pnpm-lock.yaml* ./
|
||||
|
||||
RUN <<EOF
|
||||
set -xe
|
||||
apk add libc6-compat
|
||||
apk add --virtual .gyp python3 make g++
|
||||
npm install -g pnpm
|
||||
npm install -g next
|
||||
EOF
|
||||
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store"
|
||||
|
||||
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm install -r --offline
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD ["npx", "next", "dev"]
|
||||
@@ -2,8 +2,22 @@
|
||||
|
||||
set -e
|
||||
|
||||
# Default to root, so old installations won't break
|
||||
export PUID=${PUID:-0}
|
||||
export PGID=${PGID:-0}
|
||||
|
||||
# This is in attempt to preserve the original behavior of the Dockerfile,
|
||||
# while also supporting the lscr.io /config directory
|
||||
[ ! -d "/app/config" ] && ln -s /config /app/config
|
||||
|
||||
node server.js
|
||||
# Set privileges for /app but only if pid 1 user is root and we are dropping privileges.
|
||||
# If container is run as an unprivileged user, it means owner already handled ownership setup on their own.
|
||||
# Running chown in that case (as non-root) will cause error
|
||||
[ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ] && chown -R ${PUID}:${PGID} /app
|
||||
|
||||
# Drop privileges (when asked to) if root, otherwise run as current user
|
||||
if [ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ]; then
|
||||
su-exec ${PUID}:${PGID} "$@"
|
||||
else
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
2
k3d/.envrc
Normal file
2
k3d/.envrc
Normal file
@@ -0,0 +1,2 @@
|
||||
#shellcheck disable=SC2148,SC2155
|
||||
export KUBECONFIG=$(readlink -f ./kubeconfig)
|
||||
2
k3d/.gitignore
vendored
Normal file
2
k3d/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
kubeconfig
|
||||
|
||||
64
k3d/README.md
Normal file
64
k3d/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Kubernetes Development
|
||||
|
||||
These configs and scripts attempt to simplify spinning up a kubernetes cluster
|
||||
for development and testing purposes. It leverages [k3d](https://k3d.io) to create
|
||||
a [k3s](https://k3s.io) cluster in Docker. Homepage can then be deployed either via
|
||||
the `k3d-deploy.sh` script, or [tilt](https://tilt.dev) can be used to spin up a
|
||||
local CI loop that will automatically update the deployment.
|
||||
|
||||
All the commands in the document should be run from the `k3d` directory.
|
||||
|
||||
## Requisite Tools
|
||||
|
||||
| Tool | Description |
|
||||
|-------------------------------------------------------------|----------------------------------------------------------|
|
||||
| [docker](https://docker.io) | Docker container runtime |
|
||||
| [kubectl](https://kubernetes.io/releases/download/#kubectl) | Kubernetes CLI |
|
||||
| [helm](https://helm.sh) | Kubernetes package manager |
|
||||
| [k3d](https://k3d.io) | Kubernetes on Docker - used to create the cluster |
|
||||
| [k9s](https://k9scli.io) | (Optional) Command line view for kubernetes cluster |
|
||||
| [tilt](https://tilt.dev) | (Optional) Local CI loop for kubernetes deployment |
|
||||
| [direnv](https://direnv.net/) | (Optional) Automatically loads `kubeconfig` via `.envrc` |
|
||||
|
||||
|
||||
## One-off Test Deployments
|
||||
|
||||
Create a cluster:
|
||||
|
||||
```sh
|
||||
./k3d-up.sh
|
||||
```
|
||||
|
||||
Build and deploy:
|
||||
|
||||
```sh
|
||||
./k3d-deploy.sh
|
||||
```
|
||||
|
||||
Open the Homepage deployment:
|
||||
|
||||
```sh
|
||||
xdg-open http://homepage.k3d.localhost:8080/
|
||||
```
|
||||
|
||||
## Continuous Deployment
|
||||
|
||||
Create a cluster:
|
||||
|
||||
```sh
|
||||
./k3d-up.sh
|
||||
```
|
||||
|
||||
Kick off tilt:
|
||||
|
||||
```sh
|
||||
tilt up
|
||||
```
|
||||
|
||||
Press space bar to open the tilt web UI, which is quite informative.
|
||||
|
||||
Open the Homepage deployment:
|
||||
|
||||
```sh
|
||||
xdg-open http://homepage.k3d.localhost:8080/
|
||||
```
|
||||
25
k3d/Tiltfile
Normal file
25
k3d/Tiltfile
Normal file
@@ -0,0 +1,25 @@
|
||||
docker_build('k3d-registry.localhost:55000/homepage:local', '..',
|
||||
dockerfile = "../Dockerfile-tilt",
|
||||
build_args={'node_env': 'development'},
|
||||
#entrypoint='pnpm run nodemon /app/server.js',
|
||||
live_update=[
|
||||
sync('.', '/app'),
|
||||
run('cd /app && pnpm install', trigger=['.package.json', './pnpm-lock.yaml'])
|
||||
]
|
||||
)
|
||||
load('ext://helm_resource', 'helm_resource', 'helm_repo')
|
||||
helm_repo('jameswynn', 'https://jameswynn.github.io/helm-charts')
|
||||
|
||||
helm_resource('homepage', 'jameswynn/homepage',
|
||||
image_deps=[
|
||||
"k3d-registry.localhost:55000/homepage:local"
|
||||
],
|
||||
image_keys=[
|
||||
("image.repository", "image.tag")
|
||||
],
|
||||
# image_selector= "k3d-registry.localhost:55000/homepage:local",
|
||||
flags=[
|
||||
"-f", "k3d-helm-values.yaml",
|
||||
"--set", "persistence.dotnext.enabled=true"
|
||||
]
|
||||
)
|
||||
14
k3d/k3d-deploy.sh
Executable file
14
k3d/k3d-deploy.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
DOCKER_BUILDKIT=1 docker build -t k3d-registry.localhost:55000/homepage:local ..
|
||||
docker push k3d-registry.localhost:55000/homepage:local
|
||||
|
||||
HELM_REPO_NAME=jameswynn
|
||||
HELM_REPO_URL=https://jameswynn.github.io/helm-charts
|
||||
|
||||
if ! helm repo list | grep $HELM_REPO_URL > /dev/null; then
|
||||
helm repo add $HELM_REPO_NAME $HELM_REPO_URL
|
||||
helm repo update
|
||||
fi
|
||||
|
||||
helm upgrade --install homepage jameswynn/homepage -f k3d-helm-values.yaml
|
||||
4
k3d/k3d-down.sh
Executable file
4
k3d/k3d-down.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
k3d cluster delete homepage
|
||||
rm kubeconfig
|
||||
78
k3d/k3d-helm-values.yaml
Normal file
78
k3d/k3d-helm-values.yaml
Normal file
@@ -0,0 +1,78 @@
|
||||
image:
|
||||
repository: k3d-registry.localhost:55000/homepage
|
||||
tag: local
|
||||
pullPolicy: Always
|
||||
|
||||
config:
|
||||
bookmarks:
|
||||
- Developer:
|
||||
- Github:
|
||||
- abbr: GH
|
||||
href: https://github.com/
|
||||
services:
|
||||
- My First Group:
|
||||
- My First Service:
|
||||
href: http://localhost/
|
||||
description: Homepage is awesome
|
||||
|
||||
- My Second Group:
|
||||
- My Second Service:
|
||||
href: http://localhost/
|
||||
description: Homepage is the best
|
||||
|
||||
- My Third Group:
|
||||
- My Third Service:
|
||||
href: http://localhost/
|
||||
description: Homepage is 😎
|
||||
widgets:
|
||||
# show the kubernetes widget, with the cluster summary and individual nodes
|
||||
- kubernetes:
|
||||
cluster:
|
||||
show: true
|
||||
cpu: true
|
||||
memory: true
|
||||
showLabel: true
|
||||
label: "cluster"
|
||||
nodes:
|
||||
show: true
|
||||
cpu: true
|
||||
memory: true
|
||||
showLabel: true
|
||||
- search:
|
||||
provider: duckduckgo
|
||||
target: _blank
|
||||
kubernetes:
|
||||
mode: cluster
|
||||
docker:
|
||||
settings:
|
||||
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: homepage
|
||||
|
||||
enableRbac: true
|
||||
|
||||
ingress:
|
||||
main:
|
||||
enabled: true
|
||||
annotations:
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/name: "Homepage"
|
||||
gethomepage.dev/description: "Dynamically Detected Homepage"
|
||||
gethomepage.dev/group: "Dynamic"
|
||||
gethomepage.dev/icon: "homepage.png"
|
||||
hosts:
|
||||
- host: homepage.k3d.localhost
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
|
||||
persistence:
|
||||
# this persists the .next directory which greatly improves successive pod startup times in Tilt,
|
||||
# but it breaks normal deployments, so it is disabled by default
|
||||
dotnext:
|
||||
enabled: false
|
||||
type: pvc
|
||||
accessMode: ReadWriteOnce
|
||||
size: 1Gi
|
||||
mountPath: /app/.next
|
||||
9
k3d/k3d-up.sh
Executable file
9
k3d/k3d-up.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
k3d cluster create --config k3d.yaml --wait
|
||||
k3d kubeconfig get homepage > kubeconfig
|
||||
chmod 600 kubeconfig
|
||||
export KUBECONFIG=$(pwd)/kubeconfig
|
||||
|
||||
echo "Waiting for traefik install job to complete (CTRL+C is safe if you're impatient)"
|
||||
kubectl wait jobs/helm-install-traefik -n kube-system --for condition=complete --timeout 90s && echo "Completed" || echo "Timed out (but it should still come up eventually)"
|
||||
59
k3d/k3d.yaml
Normal file
59
k3d/k3d.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
kind: Simple
|
||||
apiVersion: k3d.io/v1alpha3
|
||||
name: homepage
|
||||
servers: 1
|
||||
agents: 2
|
||||
kubeAPI:
|
||||
hostIP: 0.0.0.0
|
||||
hostPort: "6443"
|
||||
image: rancher/k3s:v1.25.5-k3s1
|
||||
volumes:
|
||||
- volume: /tmp:/tmp/k3d-homepage
|
||||
nodeFilters:
|
||||
- all
|
||||
ports:
|
||||
- port: 8080:80
|
||||
nodeFilters:
|
||||
- loadbalancer
|
||||
- port: 0.0.0.0:8443:443
|
||||
nodeFilters:
|
||||
- loadbalancer
|
||||
options:
|
||||
k3d:
|
||||
wait: true
|
||||
timeout: 6m0s
|
||||
disableLoadbalancer: false
|
||||
disableImageVolume: false
|
||||
disableRollback: false
|
||||
k3s:
|
||||
extraArgs:
|
||||
- arg: --tls-san=127.0.0.1
|
||||
nodeFilters:
|
||||
- server:*
|
||||
nodeLabels: []
|
||||
kubeconfig:
|
||||
updateDefaultKubeconfig: false
|
||||
switchCurrentContext: false
|
||||
runtime:
|
||||
gpuRequest: ""
|
||||
serversMemory: "1024Mi"
|
||||
agentsMemory: "1024Mi"
|
||||
labels:
|
||||
- label: foo=bar
|
||||
nodeFilters:
|
||||
- server:0
|
||||
- loadbalancer
|
||||
env:
|
||||
- envVar: bar=baz
|
||||
nodeFilters:
|
||||
- all
|
||||
registries:
|
||||
create:
|
||||
name: k3d-registry
|
||||
# host: 0.0.0.0
|
||||
hostPort: "55000"
|
||||
config: |
|
||||
mirrors:
|
||||
"k3d-registry.localhost:55000":
|
||||
endpoint:
|
||||
- http://k3d-registry:5000
|
||||
147
kubernetes.md
Normal file
147
kubernetes.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Kubernetes Support
|
||||
|
||||
## Requirements
|
||||
|
||||
* Kubernetes 1.19+
|
||||
* Metrics service
|
||||
* An Ingress controller
|
||||
|
||||
## Deployment
|
||||
|
||||
Use the unofficial helm chart: https://github.com/jameswynn/helm-charts/tree/main/charts/homepage
|
||||
|
||||
```sh
|
||||
helm repo add jameswynn https://jameswynn.github.io/helm-charts
|
||||
helm install my-release jameswynn/homepage
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Set the `mode` in the `kubernetes.yaml` to `cluster`.
|
||||
|
||||
```yaml
|
||||
mode: default
|
||||
```
|
||||
|
||||
## Widgets
|
||||
|
||||
The Kubernetes widget can show a high-level overview of the cluster,
|
||||
individual nodes, or both.
|
||||
|
||||
```yaml
|
||||
- kubernetes:
|
||||
cluster:
|
||||
# Shows the cluster node
|
||||
show: true
|
||||
# Shows the aggregate CPU stats
|
||||
cpu: true
|
||||
# Shows the aggregate memory stats
|
||||
memory: true
|
||||
# Shows a custom label
|
||||
showLabel: true
|
||||
label: "cluster"
|
||||
nodes:
|
||||
# Shows the clusters
|
||||
show: true
|
||||
# Shows the CPU for each node
|
||||
cpu: true
|
||||
# Shows the memory for each node
|
||||
memory: true
|
||||
# Shows the label, which is always the node name
|
||||
showLabel: true
|
||||
```
|
||||
|
||||
## Service Discovery
|
||||
|
||||
Sample yaml:
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: homepage
|
||||
annotations:
|
||||
gethomepage.dev/enabled: "true"
|
||||
gethomepage.dev/description: Dynamically Detected Homepage
|
||||
gethomepage.dev/group: Operations
|
||||
gethomepage.dev/icon: homepage.png
|
||||
gethomepage.dev/name: Homepage
|
||||
spec:
|
||||
rules:
|
||||
- host: homepage.example.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: homepage
|
||||
port:
|
||||
number: 3000
|
||||
path: /
|
||||
pathType: Prefix
|
||||
```
|
||||
|
||||
## Service Widgets
|
||||
|
||||
To manually configure a Service Widget the `namespace` and `app` fields must
|
||||
be configured on the service entry.
|
||||
|
||||
```yaml
|
||||
- Home Automation
|
||||
- Home-Assistant:
|
||||
icon: home-assistant.png
|
||||
href: https://home.example.com
|
||||
description: Home Automation
|
||||
app: home-assistant
|
||||
namespace: home
|
||||
```
|
||||
|
||||
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,
|
||||
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
|
||||
be used in it which allows for some powerful selection capabilities.
|
||||
|
||||
For instance, it can be utilized to roll multiple underlying deployments under
|
||||
one application to see a high-level aggregate:
|
||||
|
||||
```yaml
|
||||
- Comms
|
||||
- Element Chat:
|
||||
icon: matrix-light.png
|
||||
href: https://chat.example.com
|
||||
description: Matrix Synapse Powered Chat
|
||||
app: matrix-element
|
||||
namespace: comms
|
||||
podSelector: >-
|
||||
app.kubernetes.io/instance in (
|
||||
matrix-element,
|
||||
matrix-media-repo,
|
||||
matrix-media-repo-postgresql,
|
||||
matrix-synapse
|
||||
)
|
||||
```
|
||||
|
||||
## Longhorn Widget
|
||||
|
||||
There is a widget for showing storage stats from [Longhorn](https://longhorn.io).
|
||||
Configure it from the `widgets.yaml`.
|
||||
|
||||
```yaml
|
||||
- longhorn:
|
||||
# Show the expanded
|
||||
expanded: true
|
||||
# Shows a node representing the aggregate values
|
||||
total: true
|
||||
# Shows the node names as labels
|
||||
labels: true
|
||||
# Show the nodes
|
||||
nodes: true
|
||||
# An explicit list of nodes to show. All are shown by default if "nodes" is true
|
||||
include:
|
||||
- node1
|
||||
- node2
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Refer to the [k3d readme](k3d/README.md).
|
||||
8518
package-lock.json
generated
Normal file
8518
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.2",
|
||||
"@kubernetes/client-node": "^0.17.1",
|
||||
"classnames": "^2.3.2",
|
||||
"compare-versions": "^5.0.1",
|
||||
"dockerode": "^3.3.4",
|
||||
|
||||
480
pnpm-lock.yaml
generated
480
pnpm-lock.yaml
generated
@@ -2,6 +2,7 @@ lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@headlessui/react': ^1.7.2
|
||||
'@kubernetes/client-node': ^0.17.1
|
||||
'@tailwindcss/forms': ^0.5.3
|
||||
autoprefixer: ^10.4.12
|
||||
classnames: ^2.3.2
|
||||
@@ -44,6 +45,7 @@ specifiers:
|
||||
|
||||
dependencies:
|
||||
'@headlessui/react': 1.7.2_biqbaboplfbrettd7655fr4n2y
|
||||
'@kubernetes/client-node': 0.17.1
|
||||
classnames: 2.3.2
|
||||
compare-versions: 5.0.1
|
||||
dockerode: 3.3.4
|
||||
@@ -171,6 +173,30 @@ packages:
|
||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||
dev: true
|
||||
|
||||
/@kubernetes/client-node/0.17.1:
|
||||
resolution: {integrity: sha512-qXANjukuTq/drb1hq1NCYZafpdRTvbyTzbliWO6RwW7eEb2b9qwINbw0DiVHpBQg3e9DeQd8+brI1sR1Fck5kQ==}
|
||||
dependencies:
|
||||
byline: 5.0.0
|
||||
execa: 5.0.0
|
||||
isomorphic-ws: 4.0.1_ws@7.5.9
|
||||
js-yaml: 4.1.0
|
||||
jsonpath-plus: 0.19.0
|
||||
request: 2.88.2
|
||||
rfc4648: 1.5.2
|
||||
shelljs: 0.8.5
|
||||
stream-buffers: 3.0.2
|
||||
tar: 6.1.13
|
||||
tmp-promise: 3.0.3
|
||||
tslib: 1.14.1
|
||||
underscore: 1.13.6
|
||||
ws: 7.5.9
|
||||
optionalDependencies:
|
||||
openid-client: 5.3.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
dev: false
|
||||
|
||||
/@next/env/12.3.1:
|
||||
resolution: {integrity: sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==}
|
||||
dev: false
|
||||
@@ -467,7 +493,6 @@ packages:
|
||||
fast-json-stable-stringify: 2.1.0
|
||||
json-schema-traverse: 0.4.1
|
||||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/ansi-regex/5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
@@ -546,6 +571,11 @@ packages:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/assert-plus/1.0.0:
|
||||
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
|
||||
engines: {node: '>=0.8'}
|
||||
dev: false
|
||||
|
||||
/ast-types-flow/0.0.7:
|
||||
resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==}
|
||||
dev: true
|
||||
@@ -574,6 +604,14 @@ packages:
|
||||
postcss-value-parser: 4.2.0
|
||||
dev: true
|
||||
|
||||
/aws-sign2/0.7.0:
|
||||
resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
|
||||
dev: false
|
||||
|
||||
/aws4/1.12.0:
|
||||
resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==}
|
||||
dev: false
|
||||
|
||||
/axe-core/4.4.3:
|
||||
resolution: {integrity: sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -585,7 +623,6 @@ packages:
|
||||
|
||||
/balanced-match/1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
||||
/base64-js/1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
@@ -615,7 +652,6 @@ packages:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
dev: true
|
||||
|
||||
/braces/3.0.2:
|
||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||
@@ -648,6 +684,11 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/byline/5.0.0:
|
||||
resolution: {integrity: sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/bytes/3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -673,6 +714,10 @@ packages:
|
||||
/caniuse-lite/1.0.30001410:
|
||||
resolution: {integrity: sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ==}
|
||||
|
||||
/caseless/0.12.0:
|
||||
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
|
||||
dev: false
|
||||
|
||||
/chalk/4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -700,6 +745,11 @@ packages:
|
||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
||||
dev: false
|
||||
|
||||
/chownr/2.0.0:
|
||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/classnames/2.3.2:
|
||||
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
|
||||
dev: false
|
||||
@@ -758,7 +808,6 @@ packages:
|
||||
|
||||
/concat-map/0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
dev: true
|
||||
|
||||
/confusing-browser-globals/1.0.11:
|
||||
resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==}
|
||||
@@ -774,13 +823,17 @@ packages:
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
|
||||
/core-util-is/1.0.2:
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
dev: false
|
||||
|
||||
/cpu-features/0.0.4:
|
||||
resolution: {integrity: sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
buildcheck: 0.0.3
|
||||
nan: 2.16.0
|
||||
nan: 2.17.0
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -791,7 +844,6 @@ packages:
|
||||
path-key: 3.1.1
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
dev: true
|
||||
|
||||
/cssesc/3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
@@ -807,6 +859,13 @@ packages:
|
||||
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
|
||||
dev: true
|
||||
|
||||
/dashdash/1.14.1:
|
||||
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
||||
engines: {node: '>=0.10'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
dev: false
|
||||
|
||||
/debug/2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
@@ -928,6 +987,13 @@ packages:
|
||||
esutils: 2.0.3
|
||||
dev: true
|
||||
|
||||
/ecc-jsbn/0.1.2:
|
||||
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
||||
dependencies:
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/electron-to-chromium/1.4.261:
|
||||
resolution: {integrity: sha512-fVXliNUGJ7XUVJSAasPseBbVgJIeyw5M1xIkgXdTSRjlmCqBbiSTsEdLOCJS31Fc8B7CaloQ/BFAg8By3ODLdg==}
|
||||
dev: true
|
||||
@@ -1396,9 +1462,32 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/execa/5.0.0:
|
||||
resolution: {integrity: sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
get-stream: 6.0.1
|
||||
human-signals: 2.1.0
|
||||
is-stream: 2.0.1
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 4.0.1
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
dev: false
|
||||
|
||||
/extend/3.0.2:
|
||||
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
|
||||
dev: false
|
||||
|
||||
/extsprintf/1.3.0:
|
||||
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
dev: false
|
||||
|
||||
/fast-deep-equal/3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
|
||||
/fast-diff/1.2.0:
|
||||
resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==}
|
||||
@@ -1417,7 +1506,6 @@ packages:
|
||||
|
||||
/fast-json-stable-stringify/2.1.0:
|
||||
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
|
||||
dev: true
|
||||
|
||||
/fast-levenshtein/2.0.6:
|
||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||
@@ -1481,6 +1569,19 @@ packages:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/forever-agent/0.6.1:
|
||||
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
|
||||
dev: false
|
||||
|
||||
/form-data/2.3.3:
|
||||
resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
|
||||
engines: {node: '>= 0.12'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/form-data/3.0.1:
|
||||
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -1498,9 +1599,15 @@ packages:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
dev: false
|
||||
|
||||
/fs-minipass/2.1.0:
|
||||
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
dev: false
|
||||
|
||||
/fs.realpath/1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
dev: true
|
||||
|
||||
/fsevents/2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
@@ -1512,7 +1619,6 @@ packages:
|
||||
|
||||
/function-bind/1.1.1:
|
||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||
dev: true
|
||||
|
||||
/function.prototype.name/1.1.5:
|
||||
resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
|
||||
@@ -1536,6 +1642,11 @@ packages:
|
||||
has-symbols: 1.0.3
|
||||
dev: true
|
||||
|
||||
/get-stream/6.0.1:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/get-symbol-description/1.0.0:
|
||||
resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1544,6 +1655,12 @@ packages:
|
||||
get-intrinsic: 1.1.3
|
||||
dev: true
|
||||
|
||||
/getpass/0.1.7:
|
||||
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
dev: false
|
||||
|
||||
/glob-parent/5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -1578,7 +1695,6 @@ packages:
|
||||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: true
|
||||
|
||||
/globals/13.17.0:
|
||||
resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==}
|
||||
@@ -1603,6 +1719,20 @@ packages:
|
||||
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
|
||||
dev: true
|
||||
|
||||
/har-schema/2.0.0:
|
||||
resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/har-validator/5.1.5:
|
||||
resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
|
||||
engines: {node: '>=6'}
|
||||
deprecated: this library is no longer supported
|
||||
dependencies:
|
||||
ajv: 6.12.6
|
||||
har-schema: 2.0.0
|
||||
dev: false
|
||||
|
||||
/has-bigints/1.0.2:
|
||||
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
|
||||
dev: true
|
||||
@@ -1635,7 +1765,6 @@ packages:
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
dev: true
|
||||
|
||||
/hoist-non-react-statics/3.3.2:
|
||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||
@@ -1660,6 +1789,20 @@ packages:
|
||||
toidentifier: 1.0.1
|
||||
dev: false
|
||||
|
||||
/http-signature/1.2.0:
|
||||
resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
|
||||
engines: {node: '>=0.8', npm: '>=1.3.7'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
jsprim: 1.4.2
|
||||
sshpk: 1.17.0
|
||||
dev: false
|
||||
|
||||
/human-signals/2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
dev: false
|
||||
|
||||
/i18next-fs-backend/1.1.5:
|
||||
resolution: {integrity: sha512-raTel3EfshiUXxR0gvmIoqp75jhkj8+7R1LjB006VZKPTFBbXyx6TlUVhb8Z9+7ahgpFbcQg1QWVOdf/iNzI5A==}
|
||||
dev: false
|
||||
@@ -1704,7 +1847,6 @@ packages:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/inherits/2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
@@ -1718,6 +1860,11 @@ packages:
|
||||
side-channel: 1.0.4
|
||||
dev: true
|
||||
|
||||
/interpret/1.4.0:
|
||||
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
||||
|
||||
/is-arrayish/0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
dev: false
|
||||
@@ -1752,7 +1899,6 @@ packages:
|
||||
resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
|
||||
dependencies:
|
||||
has: 1.0.3
|
||||
dev: true
|
||||
|
||||
/is-date-object/1.0.5:
|
||||
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
|
||||
@@ -1823,6 +1969,10 @@ packages:
|
||||
has-symbols: 1.0.3
|
||||
dev: true
|
||||
|
||||
/is-typedarray/1.0.0:
|
||||
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
|
||||
dev: false
|
||||
|
||||
/is-weakref/1.0.2:
|
||||
resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
|
||||
dependencies:
|
||||
@@ -1831,7 +1981,23 @@ packages:
|
||||
|
||||
/isexe/2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/isomorphic-ws/4.0.1_ws@7.5.9:
|
||||
resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==}
|
||||
peerDependencies:
|
||||
ws: '*'
|
||||
dependencies:
|
||||
ws: 7.5.9
|
||||
dev: false
|
||||
|
||||
/isstream/0.1.2:
|
||||
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
|
||||
dev: false
|
||||
|
||||
/jose/4.11.2:
|
||||
resolution: {integrity: sha512-njj0VL2TsIxCtgzhO+9RRobBvws4oYyCM8TpvoUQwl/MbIM3NFJRR9+e6x0sS5xXaP1t6OCBkaBME98OV9zU5A==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/js-sdsl/4.1.4:
|
||||
resolution: {integrity: sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==}
|
||||
@@ -1846,18 +2012,29 @@ packages:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
/jsbn/0.1.1:
|
||||
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
|
||||
dev: false
|
||||
|
||||
/json-rpc-2.0/1.4.1:
|
||||
resolution: {integrity: sha512-OX1NJhpIfuK4GjDnJ/gKtZy1HOYo0l4eL0a4rb0rNeQheX1xlyQ9+JMmPzs/sFNthpS/TXKPWlGo09X7B5l81A==}
|
||||
dev: false
|
||||
|
||||
/json-schema-traverse/0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
dev: true
|
||||
|
||||
/json-schema/0.4.0:
|
||||
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
|
||||
dev: false
|
||||
|
||||
/json-stable-stringify-without-jsonify/1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
dev: true
|
||||
|
||||
/json-stringify-safe/5.0.1:
|
||||
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
|
||||
dev: false
|
||||
|
||||
/json5/1.0.1:
|
||||
resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==}
|
||||
hasBin: true
|
||||
@@ -1865,6 +2042,21 @@ packages:
|
||||
minimist: 1.2.6
|
||||
dev: true
|
||||
|
||||
/jsonpath-plus/0.19.0:
|
||||
resolution: {integrity: sha512-GSVwsrzW9LsA5lzsqe4CkuZ9wp+kxBb2GwNniaWzI2YFn5Ig42rSW8ZxVpWXaAfakXNrx5pgY5AbQq7kzX29kg==}
|
||||
engines: {node: '>=6.0'}
|
||||
dev: false
|
||||
|
||||
/jsprim/1.4.2:
|
||||
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
extsprintf: 1.3.0
|
||||
json-schema: 0.4.0
|
||||
verror: 1.10.0
|
||||
dev: false
|
||||
|
||||
/jsx-ast-utils/3.3.3:
|
||||
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
|
||||
engines: {node: '>=4.0'}
|
||||
@@ -1932,12 +2124,15 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/memory-cache/0.2.0:
|
||||
resolution: {integrity: sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==}
|
||||
dev: false
|
||||
|
||||
/merge-stream/2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
dev: false
|
||||
|
||||
/merge2/1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1963,6 +2158,11 @@ packages:
|
||||
mime-db: 1.52.0
|
||||
dev: false
|
||||
|
||||
/mimic-fn/2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/mini-svg-data-uri/1.4.4:
|
||||
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
|
||||
hasBin: true
|
||||
@@ -1972,16 +2172,43 @@ packages:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
dev: true
|
||||
|
||||
/minimist/1.2.6:
|
||||
resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
|
||||
dev: true
|
||||
|
||||
/minipass/3.3.6:
|
||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/minipass/4.0.0:
|
||||
resolution: {integrity: sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/minizlib/2.1.2:
|
||||
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/mkdirp-classic/0.5.3:
|
||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||
dev: false
|
||||
|
||||
/mkdirp/1.0.4:
|
||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/ms/2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
dev: true
|
||||
@@ -1992,8 +2219,8 @@ packages:
|
||||
/ms/2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
/nan/2.16.0:
|
||||
resolution: {integrity: sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==}
|
||||
/nan/2.17.0:
|
||||
resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
@@ -2102,11 +2329,28 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/npm-run-path/4.0.1:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
dev: false
|
||||
|
||||
/oauth-sign/0.9.0:
|
||||
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
|
||||
dev: false
|
||||
|
||||
/object-assign/4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/object-hash/2.2.0:
|
||||
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/object-hash/3.0.0:
|
||||
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -2165,6 +2409,12 @@ packages:
|
||||
es-abstract: 1.20.3
|
||||
dev: true
|
||||
|
||||
/oidc-token-hash/5.0.1:
|
||||
resolution: {integrity: sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==}
|
||||
engines: {node: ^10.13.0 || >=12.0.0}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/once/1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
@@ -2176,6 +2426,24 @@ packages:
|
||||
fn.name: 1.1.0
|
||||
dev: false
|
||||
|
||||
/onetime/5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
dev: false
|
||||
|
||||
/openid-client/5.3.1:
|
||||
resolution: {integrity: sha512-RLfehQiHch9N6tRWNx68cicf3b1WR0x74bJWHRc25uYIbSRwjxYcTFaRnzbbpls5jroLAaB/bFIodTgA5LJMvw==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
jose: 4.11.2
|
||||
lru-cache: 6.0.0
|
||||
object-hash: 2.2.0
|
||||
oidc-token-hash: 5.0.1
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/optionator/0.9.1:
|
||||
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -2217,22 +2485,23 @@ packages:
|
||||
/path-is-absolute/1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/path-key/3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/path-parse/1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
dev: true
|
||||
|
||||
/path-type/4.0.0:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/performance-now/2.1.0:
|
||||
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
|
||||
dev: false
|
||||
|
||||
/picocolors/1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
|
||||
@@ -2371,6 +2640,11 @@ packages:
|
||||
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
/qs/6.5.3:
|
||||
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/querystringify/2.2.0:
|
||||
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
|
||||
dev: false
|
||||
@@ -2464,6 +2738,13 @@ packages:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/rechoir/0.6.2:
|
||||
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dependencies:
|
||||
resolve: 1.22.1
|
||||
dev: false
|
||||
|
||||
/regenerator-runtime/0.13.9:
|
||||
resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
|
||||
|
||||
@@ -2481,6 +2762,33 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/request/2.88.2:
|
||||
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
|
||||
engines: {node: '>= 6'}
|
||||
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
|
||||
dependencies:
|
||||
aws-sign2: 0.7.0
|
||||
aws4: 1.12.0
|
||||
caseless: 0.12.0
|
||||
combined-stream: 1.0.8
|
||||
extend: 3.0.2
|
||||
forever-agent: 0.6.1
|
||||
form-data: 2.3.3
|
||||
har-validator: 5.1.5
|
||||
http-signature: 1.2.0
|
||||
is-typedarray: 1.0.0
|
||||
isstream: 0.1.2
|
||||
json-stringify-safe: 5.0.1
|
||||
mime-types: 2.1.35
|
||||
oauth-sign: 0.9.0
|
||||
performance-now: 2.1.0
|
||||
qs: 6.5.3
|
||||
safe-buffer: 5.2.1
|
||||
tough-cookie: 2.5.0
|
||||
tunnel-agent: 0.6.0
|
||||
uuid: 3.4.0
|
||||
dev: false
|
||||
|
||||
/requires-port/1.0.0:
|
||||
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
|
||||
dev: false
|
||||
@@ -2497,7 +2805,6 @@ packages:
|
||||
is-core-module: 2.10.0
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: true
|
||||
|
||||
/resolve/2.0.0-next.4:
|
||||
resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==}
|
||||
@@ -2513,12 +2820,15 @@ packages:
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/rfc4648/1.5.2:
|
||||
resolution: {integrity: sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==}
|
||||
dev: false
|
||||
|
||||
/rimraf/3.0.2:
|
||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/run-parallel/1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
@@ -2588,12 +2898,20 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
shebang-regex: 3.0.0
|
||||
dev: true
|
||||
|
||||
/shebang-regex/3.0.0:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/shelljs/0.8.5:
|
||||
resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
interpret: 1.4.0
|
||||
rechoir: 0.6.2
|
||||
dev: false
|
||||
|
||||
/shvl/3.0.0:
|
||||
resolution: {integrity: sha512-5IomAM3ykE/g9K9L6lhODc+TpCuN03rrhlboegeKyyfh66DDdpRD5JN37DYhNHH+RaYjiIDx64K/Ms/xQYOR5w==}
|
||||
@@ -2607,6 +2925,10 @@ packages:
|
||||
object-inspect: 1.12.2
|
||||
dev: true
|
||||
|
||||
/signal-exit/3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
dev: false
|
||||
|
||||
/simple-swizzle/0.2.2:
|
||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||
dependencies:
|
||||
@@ -2635,7 +2957,23 @@ packages:
|
||||
bcrypt-pbkdf: 1.0.2
|
||||
optionalDependencies:
|
||||
cpu-features: 0.0.4
|
||||
nan: 2.16.0
|
||||
nan: 2.17.0
|
||||
dev: false
|
||||
|
||||
/sshpk/1.17.0:
|
||||
resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
asn1: 0.2.6
|
||||
assert-plus: 1.0.0
|
||||
bcrypt-pbkdf: 1.0.2
|
||||
dashdash: 1.14.1
|
||||
ecc-jsbn: 0.1.2
|
||||
getpass: 0.1.7
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
tweetnacl: 0.14.5
|
||||
dev: false
|
||||
|
||||
/stack-trace/0.0.10:
|
||||
@@ -2647,6 +2985,11 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/stream-buffers/3.0.2:
|
||||
resolution: {integrity: sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
dev: false
|
||||
|
||||
/string.prototype.matchall/4.0.7:
|
||||
resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==}
|
||||
dependencies:
|
||||
@@ -2694,6 +3037,11 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/strip-final-newline/2.0.0:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/strip-json-comments/3.1.1:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2725,7 +3073,6 @@ packages:
|
||||
/supports-preserve-symlinks-flag/1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/swr/1.3.0_react@18.2.0:
|
||||
resolution: {integrity: sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==}
|
||||
@@ -2797,6 +3144,18 @@ packages:
|
||||
readable-stream: 3.6.0
|
||||
dev: false
|
||||
|
||||
/tar/6.1.13:
|
||||
resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
chownr: 2.0.0
|
||||
fs-minipass: 2.1.0
|
||||
minipass: 4.0.0
|
||||
minizlib: 2.1.2
|
||||
mkdirp: 1.0.4
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/text-hex/1.0.0:
|
||||
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
|
||||
dev: false
|
||||
@@ -2805,6 +3164,19 @@ packages:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
dev: true
|
||||
|
||||
/tmp-promise/3.0.3:
|
||||
resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
|
||||
dependencies:
|
||||
tmp: 0.2.1
|
||||
dev: false
|
||||
|
||||
/tmp/0.2.1:
|
||||
resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==}
|
||||
engines: {node: '>=8.17.0'}
|
||||
dependencies:
|
||||
rimraf: 3.0.2
|
||||
dev: false
|
||||
|
||||
/to-regex-range/5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
@@ -2817,6 +3189,14 @@ packages:
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/tough-cookie/2.5.0:
|
||||
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
|
||||
engines: {node: '>=0.8'}
|
||||
dependencies:
|
||||
psl: 1.9.0
|
||||
punycode: 2.1.1
|
||||
dev: false
|
||||
|
||||
/tough-cookie/4.1.2:
|
||||
resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -2846,7 +3226,6 @@ packages:
|
||||
|
||||
/tslib/1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
||||
/tslib/2.4.0:
|
||||
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
|
||||
@@ -2862,6 +3241,12 @@ packages:
|
||||
typescript: 4.8.3
|
||||
dev: true
|
||||
|
||||
/tunnel-agent/0.6.0:
|
||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/tweetnacl/0.14.5:
|
||||
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
|
||||
dev: false
|
||||
@@ -2893,6 +3278,10 @@ packages:
|
||||
which-boxed-primitive: 1.0.2
|
||||
dev: true
|
||||
|
||||
/underscore/1.13.6:
|
||||
resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==}
|
||||
dev: false
|
||||
|
||||
/universalify/0.2.0:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
@@ -2918,7 +3307,6 @@ packages:
|
||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
dependencies:
|
||||
punycode: 2.1.1
|
||||
dev: true
|
||||
|
||||
/url-parse/1.5.10:
|
||||
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
||||
@@ -2938,6 +3326,21 @@ packages:
|
||||
/util-deprecate/1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
/uuid/3.4.0:
|
||||
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
|
||||
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/verror/1.10.0:
|
||||
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.3.0
|
||||
dev: false
|
||||
|
||||
/void-elements/3.1.0:
|
||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -2970,7 +3373,6 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
dev: true
|
||||
|
||||
/winston-transport/4.5.0:
|
||||
resolution: {integrity: sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==}
|
||||
@@ -3006,6 +3408,19 @@ packages:
|
||||
/wrappy/1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
/ws/7.5.9:
|
||||
resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==}
|
||||
engines: {node: '>=8.3.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ^5.0.2
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/xml-js/1.6.11:
|
||||
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
|
||||
hasBin: true
|
||||
@@ -3020,7 +3435,6 @@ packages:
|
||||
|
||||
/yallist/4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
||||
/yaml/1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
"missing_type": "نوع القطعة مفقود: {{type}}",
|
||||
"api_error": "API خطأ",
|
||||
"status": "الحالة",
|
||||
"information": "Information",
|
||||
"information": "معلومات",
|
||||
"url": "URL",
|
||||
"raw_error": "Raw Error",
|
||||
"response_data": "Response Data"
|
||||
"response_data": "بيانات الاستجابة"
|
||||
},
|
||||
"weather": {
|
||||
"current": "الموقع الحالي",
|
||||
"allow": "اضغط للسماح",
|
||||
"allow": "أنقر للسماح",
|
||||
"updating": "جاري التحديث",
|
||||
"wait": "الرجاء الانتظار"
|
||||
"wait": "الرجاء الإنتظار"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "بحث …"
|
||||
@@ -27,88 +27,88 @@
|
||||
"unifi": {
|
||||
"users": "المستخدمون",
|
||||
"uptime": "مدة تشغيل النظام",
|
||||
"days": "ايام",
|
||||
"days": "أيام",
|
||||
"wan": "WAN",
|
||||
"lan": "LAN",
|
||||
"wlan": "WLAN",
|
||||
"devices": "الاجهزة",
|
||||
"lan_devices": "LAN اجهزة",
|
||||
"wlan_devices": "WLAN احهزة",
|
||||
"devices": "الأجهزة",
|
||||
"lan_devices": "LAN أجهزة",
|
||||
"wlan_devices": "WLAN أجهزة",
|
||||
"lan_users": "LAN مستخدمين",
|
||||
"wlan_users": "WLAN مستخدمين",
|
||||
"up": "اعلي",
|
||||
"down": "اسفل",
|
||||
"wait": "الرجاء الانتظار"
|
||||
"up": "يعمل",
|
||||
"down": "لا يعمل",
|
||||
"wait": "الرجاء الإنتظار"
|
||||
},
|
||||
"wmo": {
|
||||
"73-day": "Snow",
|
||||
"0-day": "Sunny",
|
||||
"0-night": "Clear",
|
||||
"1-day": "Mainly Sunny",
|
||||
"1-night": "Mainly Clear",
|
||||
"2-day": "Partly Cloudy",
|
||||
"2-night": "Partly Cloudy",
|
||||
"3-day": "Cloudy",
|
||||
"3-night": "Cloudy",
|
||||
"45-day": "Foggy",
|
||||
"45-night": "Foggy",
|
||||
"48-day": "Foggy",
|
||||
"48-night": "Foggy",
|
||||
"51-day": "Light Drizzle",
|
||||
"51-night": "Light Drizzle",
|
||||
"53-day": "Drizzle",
|
||||
"53-night": "Drizzle",
|
||||
"55-day": "Heavy Drizzle",
|
||||
"55-night": "Heavy Drizzle",
|
||||
"56-day": "Light Freezing Drizzle",
|
||||
"56-night": "Light Freezing Drizzle",
|
||||
"57-day": "Freezing Drizzle",
|
||||
"57-night": "Freezing Drizzle",
|
||||
"61-day": "Light Rain",
|
||||
"61-night": "Light Rain",
|
||||
"63-day": "Rain",
|
||||
"63-night": "Rain",
|
||||
"65-day": "Heavy Rain",
|
||||
"65-night": "Heavy Rain",
|
||||
"66-day": "Freezing Rain",
|
||||
"66-night": "Freezing Rain",
|
||||
"67-day": "Freezing Rain",
|
||||
"67-night": "Freezing Rain",
|
||||
"71-day": "Light Snow",
|
||||
"71-night": "Light Snow",
|
||||
"73-night": "Snow",
|
||||
"75-day": "Heavy Snow",
|
||||
"75-night": "Heavy Snow",
|
||||
"77-day": "Snow Grains",
|
||||
"77-night": "Snow Grains",
|
||||
"80-day": "Light Showers",
|
||||
"80-night": "Light Showers",
|
||||
"81-day": "Showers",
|
||||
"81-night": "Showers",
|
||||
"82-day": "Heavy Showers",
|
||||
"82-night": "Heavy Showers",
|
||||
"85-day": "Snow Showers",
|
||||
"85-night": "Snow Showers",
|
||||
"86-day": "Snow Showers",
|
||||
"86-night": "Snow Showers",
|
||||
"95-day": "Thunderstorm",
|
||||
"95-night": "Thunderstorm",
|
||||
"96-day": "Thunderstorm With Hail",
|
||||
"96-night": "Thunderstorm With Hail",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail"
|
||||
"73-day": "ثلج",
|
||||
"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-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": "عاصفة رعدية مع مطر"
|
||||
},
|
||||
"docker": {
|
||||
"rx": "RX",
|
||||
"tx": "TX",
|
||||
"mem": "الرام",
|
||||
"mem": "الذاكرة",
|
||||
"cpu": "المعالج",
|
||||
"offline": "غير متصل",
|
||||
"error": "Error",
|
||||
"unknown": "Unknown"
|
||||
"error": "خطأ",
|
||||
"unknown": "مجهول"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "يعمل الان",
|
||||
"playing": "يعمل الآن",
|
||||
"transcoding": "التحويل",
|
||||
"bitrate": "معدل البت",
|
||||
"no_active": "No Active Streams"
|
||||
@@ -118,290 +118,325 @@
|
||||
"diffsDetected": "Diffs Detected"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Playing",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Bitrate",
|
||||
"playing": "يشتغل",
|
||||
"transcoding": "التحويل",
|
||||
"bitrate": "معدل البت",
|
||||
"no_active": "No Active Streams"
|
||||
},
|
||||
"nzbget": {
|
||||
"rate": "Rate",
|
||||
"remaining": "Remaining",
|
||||
"downloaded": "Downloaded"
|
||||
"rate": "معدل",
|
||||
"remaining": "متبقي",
|
||||
"downloaded": "مُنزل"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Active Streams",
|
||||
"movies": "Movies",
|
||||
"tv": "TV Shows"
|
||||
"movies": "أفلام",
|
||||
"tv": "مسلسلات"
|
||||
},
|
||||
"sabnzbd": {
|
||||
"rate": "Rate",
|
||||
"queue": "Queue",
|
||||
"timeleft": "Time Left"
|
||||
"rate": "معدل",
|
||||
"queue": "إنتظار",
|
||||
"timeleft": "الوقت المتبقي"
|
||||
},
|
||||
"rutorrent": {
|
||||
"active": "Active",
|
||||
"upload": "Upload",
|
||||
"download": "Download"
|
||||
"active": "نشط",
|
||||
"upload": "تحميل",
|
||||
"download": "تنزيل"
|
||||
},
|
||||
"transmission": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "تنزيل",
|
||||
"upload": "تحميل",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "تنزيل",
|
||||
"upload": "تحميل",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
"wanted": "مطلوب",
|
||||
"queued": "في الإنتظار",
|
||||
"series": "سلسلة"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Wanted",
|
||||
"missing": "Missing",
|
||||
"queued": "Queued",
|
||||
"movies": "Movies"
|
||||
"wanted": "مطلوب",
|
||||
"missing": "مفقود",
|
||||
"queued": "في الإنتظار",
|
||||
"movies": "أفلام"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"wanted": "مطلوب",
|
||||
"queued": "في الإنتظار",
|
||||
"albums": "ألبومات"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"books": "Books"
|
||||
"wanted": "مطلوب",
|
||||
"queued": "في الإنتظار",
|
||||
"books": "كتب"
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "Missing Episodes",
|
||||
"missingMovies": "Missing Movies"
|
||||
"missingEpisodes": "حلقات مفقودة",
|
||||
"missingMovies": "أفلام مفقودة"
|
||||
},
|
||||
"ombi": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "معلق",
|
||||
"approved": "مصدق",
|
||||
"available": "متاح"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "معلق",
|
||||
"approved": "مصدق",
|
||||
"available": "متاح"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available",
|
||||
"processing": "Processing"
|
||||
"pending": "معلق",
|
||||
"approved": "مصدق",
|
||||
"available": "متاح",
|
||||
"processing": "معالجة"
|
||||
},
|
||||
"pihole": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"gravity": "Gravity"
|
||||
"queries": "الاستعلامات",
|
||||
"blocked": "محظور",
|
||||
"gravity": "الجاذبية"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"filtered": "Filtered",
|
||||
"latency": "Latency"
|
||||
"queries": "الاستعلامات",
|
||||
"blocked": "محظور",
|
||||
"filtered": "مرشح",
|
||||
"latency": "الإستجابة"
|
||||
},
|
||||
"speedtest": {
|
||||
"upload": "Upload",
|
||||
"download": "Download",
|
||||
"upload": "التحميل",
|
||||
"download": "تنزيل",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"portainer": {
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"total": "Total"
|
||||
"running": "يعمل",
|
||||
"stopped": "متوقف",
|
||||
"total": "مجموع"
|
||||
},
|
||||
"traefik": {
|
||||
"routers": "Routers",
|
||||
"services": "Services",
|
||||
"middleware": "Middleware"
|
||||
"routers": "راوتر",
|
||||
"services": "خدمات",
|
||||
"middleware": "الوسيطة"
|
||||
},
|
||||
"npm": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"total": "Total"
|
||||
"enabled": "مفعل",
|
||||
"disabled": "معطل",
|
||||
"total": "مجموع"
|
||||
},
|
||||
"coinmarketcap": {
|
||||
"configure": "Configure one or more crypto currencies to track",
|
||||
"1hour": "1 Hour",
|
||||
"1day": "1 Day",
|
||||
"7days": "7 Days",
|
||||
"30days": "30 Days"
|
||||
"configure": "قم بأنشاء عملة تشفير واحدة أو أكثر للتتبع",
|
||||
"1hour": "١ ساعة",
|
||||
"1day": "١ يوم",
|
||||
"7days": "٧ أيام",
|
||||
"30days": "٣٠ يوم"
|
||||
},
|
||||
"gotify": {
|
||||
"apps": "Applications",
|
||||
"clients": "Clients",
|
||||
"messages": "Messages"
|
||||
"apps": "التطبيقات",
|
||||
"clients": "العملاء",
|
||||
"messages": "الرسائل"
|
||||
},
|
||||
"prowlarr": {
|
||||
"enableIndexers": "Indexers",
|
||||
"enableIndexers": "مفهرسات",
|
||||
"numberOfGrabs": "Grabs",
|
||||
"numberOfQueries": "Queries",
|
||||
"numberOfQueries": "الاستعلامات",
|
||||
"numberOfFailGrabs": "Fail Grabs",
|
||||
"numberOfFailQueries": "Fail Queries"
|
||||
"numberOfFailQueries": "فشل الاستعلامات"
|
||||
},
|
||||
"jackett": {
|
||||
"configured": "Configured",
|
||||
"errored": "Errored"
|
||||
"errored": "خطأ"
|
||||
},
|
||||
"strelaysrv": {
|
||||
"numActiveSessions": "Sessions",
|
||||
"numConnections": "Connections",
|
||||
"numActiveSessions": "الجلسات",
|
||||
"numConnections": "التوصيلات",
|
||||
"dataRelayed": "Relayed",
|
||||
"transferRate": "Rate"
|
||||
"transferRate": "معدل"
|
||||
},
|
||||
"mastodon": {
|
||||
"user_count": "Users",
|
||||
"user_count": "المستخدمين",
|
||||
"status_count": "Posts",
|
||||
"domain_count": "Domains"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
"users": "المستخدمين",
|
||||
"loginsLast24H": "تسجيلات الدخول (٢٤س)",
|
||||
"failedLoginsLast24H": "فشل تسجيلات الدخول (٢٤س)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"cpu": "CPU",
|
||||
"mem": "الذاكرة",
|
||||
"cpu": "المعالج",
|
||||
"lxc": "LXC",
|
||||
"vms": "VMs"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "CPU",
|
||||
"mem": "MEM",
|
||||
"wait": "Please wait"
|
||||
"cpu": "معالج",
|
||||
"mem": "الذاكرة",
|
||||
"wait": "الرجاء الإنتظار"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"bookmark": "مفضلة",
|
||||
"service": "خدمة",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
"updates": "Updates",
|
||||
"update_available": "Update Available",
|
||||
"up_to_date": "Up to Date",
|
||||
"available_update": "نظام",
|
||||
"updates": "تحديثات",
|
||||
"update_available": "تحديث متاح",
|
||||
"up_to_date": "حتى الآن",
|
||||
"child_bridges": "Child Bridges",
|
||||
"child_bridges_status": "{{ok}}/{{total}}"
|
||||
},
|
||||
"watchtower": {
|
||||
"containers_scanned": "Scanned",
|
||||
"containers_updated": "Updated",
|
||||
"containers_failed": "Failed"
|
||||
"containers_updated": "محدث",
|
||||
"containers_failed": "فشل"
|
||||
},
|
||||
"autobrr": {
|
||||
"approvedPushes": "Approved",
|
||||
"rejectedPushes": "Rejected",
|
||||
"filters": "Filters",
|
||||
"indexers": "Indexers"
|
||||
"approvedPushes": "مصدق",
|
||||
"rejectedPushes": "مرفوض",
|
||||
"filters": "المرشحات",
|
||||
"indexers": "مفهرسات"
|
||||
},
|
||||
"tubearchivist": {
|
||||
"downloads": "Queue",
|
||||
"videos": "Videos",
|
||||
"channels": "Channels",
|
||||
"playlists": "Playlists"
|
||||
"downloads": "إنتظار",
|
||||
"videos": "الفيديوهات",
|
||||
"channels": "القنوات",
|
||||
"playlists": "قوائم التشغيل"
|
||||
},
|
||||
"truenas": {
|
||||
"load": "System Load",
|
||||
"uptime": "Uptime",
|
||||
"alerts": "Alerts",
|
||||
"load": "حمل النظام",
|
||||
"uptime": "مدة التشغيل",
|
||||
"alerts": "تنبيهات",
|
||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
"please_wait": "الرجاء الإنتظار"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
"active": "Active",
|
||||
"queue": "Queue",
|
||||
"total": "Total"
|
||||
"speed": "السرعة",
|
||||
"active": "نشط",
|
||||
"queue": "إنتظار",
|
||||
"total": "مجموع"
|
||||
},
|
||||
"gluetun": {
|
||||
"public_ip": "Public IP",
|
||||
"region": "Region",
|
||||
"country": "Country"
|
||||
"public_ip": "العام IP",
|
||||
"region": "منطقة",
|
||||
"country": "الدولة"
|
||||
},
|
||||
"hdhomerun": {
|
||||
"channels": "Channels",
|
||||
"channels": "قنوات",
|
||||
"hd": "HD"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "خطأ",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"scrutiny": {
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"unknown": "Unknown"
|
||||
"passed": "إجتاز",
|
||||
"failed": "فشل",
|
||||
"unknown": "مجهول"
|
||||
},
|
||||
"paperlessngx": {
|
||||
"inbox": "Inbox",
|
||||
"total": "Total"
|
||||
"inbox": "صندوق الوارد",
|
||||
"total": "المجموع"
|
||||
},
|
||||
"deluge": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "تنزيل",
|
||||
"upload": "تحميل",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"flood": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "التنزيل",
|
||||
"upload": "التحميل",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Queue",
|
||||
"processed": "Processed",
|
||||
"errored": "Errored",
|
||||
"saved": "Saved"
|
||||
"queue": "إنتظار",
|
||||
"processed": "معالجة",
|
||||
"errored": "خطأ",
|
||||
"saved": "حفظ"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
"read": "قراءة",
|
||||
"unread": "غير مقروء"
|
||||
},
|
||||
"nextdns": {
|
||||
"wait": "Please Wait",
|
||||
"no_devices": "No Device Data Received"
|
||||
"wait": "الرجاء الإنتظار",
|
||||
"no_devices": "لم يتم استلام بيانات الجهاز"
|
||||
},
|
||||
"common": {
|
||||
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||
},
|
||||
"omada": {
|
||||
"connectedAp": "Connected APs",
|
||||
"activeUser": "Active devices",
|
||||
"alerts": "Alerts",
|
||||
"connectedAp": "المتصلة APs",
|
||||
"activeUser": "الأجهزة النشطة",
|
||||
"alerts": "تنبيهات",
|
||||
"connectedGateway": "Connected gateways",
|
||||
"connectedSwitches": "Connected switches"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"download": "تنزيل",
|
||||
"upload": "تحميل",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
"memoryUsed": "Memory Used",
|
||||
"uptime": "Uptime",
|
||||
"cpuLoad": "حمل المعالج",
|
||||
"memoryUsed": "الذاكرة الستخدمة",
|
||||
"uptime": "مدة التشغيل",
|
||||
"numberOfLeases": "Leases"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
"streams_xepg": "XEPG قنوات"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
"cpu": "حمل المعالج",
|
||||
"memory": "الذاكرة النشطة",
|
||||
"wanUpload": "WAN التحميل",
|
||||
"wanDownload": "WAN التنزيل"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "حالة الطابعة",
|
||||
"print_status": "حالة الطابعة",
|
||||
"print_progress": "تقدم",
|
||||
"layers": "طبقات"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "مطلوب",
|
||||
"queued": "في الإنتظار",
|
||||
"series": "سلسلة"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "حالة",
|
||||
"temp_tool": "أداة درجة الحرارة",
|
||||
"temp_bed": "درجة حرارة السرير",
|
||||
"job_completion": "إتمام"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "حالة"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"print_progress": "Progress",
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
"failedLoginsLast24H": "Errors d'inici de sessió (24h)"
|
||||
},
|
||||
"proxmox": {
|
||||
"vms": "Màquines Virtuals",
|
||||
"vms": "VMs",
|
||||
"mem": "Memòria",
|
||||
"cpu": "Processador",
|
||||
"lxc": "LXC"
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Marcador",
|
||||
"service": "Servei"
|
||||
"service": "Servei",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sistema",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +291,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Záložka",
|
||||
"service": "Služba"
|
||||
"service": "Služba",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"update_available": "Dostupná aktualizace",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"print_progress": "Progress",
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +287,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bogmærker",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"watchtower": {
|
||||
"containers_scanned": "Scannet",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Lesezeichen",
|
||||
"service": "Dienst"
|
||||
"service": "Dienst",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"cpu_usage": "CPU",
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +255,11 @@
|
||||
"status_count": "Posts",
|
||||
"domain_count": "Domains"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
@@ -277,7 +282,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Sunny",
|
||||
@@ -412,5 +419,40 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
},
|
||||
"uptimekuma": {
|
||||
"up": "Sites Up",
|
||||
"down": "Sites Down",
|
||||
"uptime": "Uptime",
|
||||
"incident": "Incident",
|
||||
"m": "m"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Servo"
|
||||
"service": "Servo",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Suna",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"layers": "Layers",
|
||||
"print_progress": "Progress"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
"qbittorrent": {
|
||||
"download": "Bajada",
|
||||
"upload": "Subida",
|
||||
"leech": "Leech",
|
||||
"leech": "Depender",
|
||||
"seed": "Semillas"
|
||||
},
|
||||
"mastodon": {
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Marcadores",
|
||||
"service": "Servicio"
|
||||
"service": "Servicio",
|
||||
"search": "Buscar",
|
||||
"custom": "Personalizado"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sistema",
|
||||
@@ -347,14 +349,14 @@
|
||||
"deluge": {
|
||||
"download": "Descarga",
|
||||
"upload": "Subida",
|
||||
"leech": "Leech",
|
||||
"leech": "Depender",
|
||||
"seed": "Semilla"
|
||||
},
|
||||
"flood": {
|
||||
"download": "Descargar",
|
||||
"upload": "Subir",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Depender",
|
||||
"seed": "Semillas"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Cola",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Memoria activa",
|
||||
"wanUpload": "Carga WAN",
|
||||
"wanDownload": "Descargar WAN"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Estado de la impresora",
|
||||
"print_status": "Estado de la impresora",
|
||||
"print_progress": "Progreso",
|
||||
"layers": "Capas"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Querido",
|
||||
"queued": "A la espera",
|
||||
"series": "Serie"
|
||||
},
|
||||
"octoprint": {
|
||||
"temp_bed": "Bed temp",
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "IP de origen",
|
||||
"status": "Estado"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"cpu_usage": "CPU",
|
||||
"datastore_usage": "Almacén de datos",
|
||||
"failed_tasks_24h": "Tareas fallidas en 24h",
|
||||
"memory_usage": "Memoria"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Usuarios",
|
||||
"photos": "Fotos",
|
||||
"videos": "Vídeos",
|
||||
"storage": "Almacenamiento"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
"uptime": "System Uptime",
|
||||
"lan_users": "LAN Users",
|
||||
"wlan_users": "WLAN Users",
|
||||
"wait": "Please wait",
|
||||
"wait": "Odota, ole hyvä",
|
||||
"days": "Days",
|
||||
"wan": "WAN",
|
||||
"up": "UP",
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -314,7 +316,7 @@
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
"please_wait": "Odota, ole hyvä"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Haluttu",
|
||||
"queued": "Jonossa",
|
||||
"series": "Sarja"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Signet",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Recherche",
|
||||
"custom": "Personnalisé"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Système",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Mém. Utilisée",
|
||||
"wanUpload": "WAN Envoi",
|
||||
"wanDownload": "WAN Récep."
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "État Imprimante",
|
||||
"print_status": "Statut Imprimante",
|
||||
"print_progress": "Progression",
|
||||
"layers": "Couches"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Demande",
|
||||
"queued": "En attente",
|
||||
"series": "Séries"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Achèvement"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "IP Publique",
|
||||
"status": "Statut"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Tâches échouées 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Mémoire"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Utilisateurs",
|
||||
"photos": "Photos",
|
||||
"videos": "Vidéos",
|
||||
"storage": "Stockage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Sunny",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,13 +77,13 @@
|
||||
"emby": {
|
||||
"playing": "Reprodukcija",
|
||||
"transcoding": "Prekodiranje",
|
||||
"bitrate": "Brzina prijenosa",
|
||||
"bitrate": "Stopa bitova",
|
||||
"no_active": "Nema aktivnih prijenosa"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Reprodukcija",
|
||||
"transcoding": "Prekodiranje",
|
||||
"bitrate": "Brzina prijenosa",
|
||||
"bitrate": "Stopa bitova",
|
||||
"no_active": "Nema aktivnih prijenosa"
|
||||
},
|
||||
"nzbget": {
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Straničnik",
|
||||
"service": "Usluga"
|
||||
"service": "Usluga",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sustav",
|
||||
@@ -388,10 +390,10 @@
|
||||
"seed": "Prenošenje preuzetog sadržaja"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
"cpuLoad": "CPU opterećenje",
|
||||
"memoryUsed": "Korištena memorija",
|
||||
"uptime": "Uptime",
|
||||
"numberOfLeases": "Leases"
|
||||
"uptime": "Radno vrijeme",
|
||||
"numberOfLeases": "Unajmljivanja"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "Svi prijenosi",
|
||||
@@ -399,9 +401,42 @@
|
||||
"streams_xepg": "XEPG kanali"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"cpu": "CPU opterećenje",
|
||||
"memory": "Aktivna memorija",
|
||||
"wanUpload": "WAN prijenos",
|
||||
"wanDownload": "WAN preuzimanje"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"layers": "Layers",
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"total": "Totale",
|
||||
"free": "Libero",
|
||||
"used": "In utilizzo",
|
||||
"load": "Carica",
|
||||
"load": "Carico",
|
||||
"cpu": "CPU"
|
||||
},
|
||||
"rutorrent": {
|
||||
@@ -175,7 +175,7 @@
|
||||
"strelaysrv": {
|
||||
"numActiveSessions": "Sessioni",
|
||||
"numConnections": "Connessioni",
|
||||
"dataRelayed": "Ritrasmettessi",
|
||||
"dataRelayed": "Ritrasmessi",
|
||||
"transferRate": "Velocità"
|
||||
},
|
||||
"authentik": {
|
||||
@@ -222,10 +222,10 @@
|
||||
"wmo": {
|
||||
"65-day": "Pioggia Intensa",
|
||||
"2-night": "Parzialmente Nuvoloso",
|
||||
"0-day": "Solleggiato",
|
||||
"0-night": "Pulisci",
|
||||
"1-day": "Principalmente Soleggiato",
|
||||
"1-night": "Principalmente Sereno",
|
||||
"0-day": "Soleggiato",
|
||||
"0-night": "Sereno",
|
||||
"1-day": "Prevalentemente Soleggiato",
|
||||
"1-night": "Prevalentemente Sereno",
|
||||
"2-day": "Parzialmente Nuvoloso",
|
||||
"3-day": "Nuvoloso",
|
||||
"3-night": "Nuvoloso",
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Segnalibro",
|
||||
"service": "Servizio"
|
||||
"service": "Servizio",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sistema",
|
||||
@@ -314,7 +316,7 @@
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "Nessun Sistema Attivo",
|
||||
"please_wait": "Attendere, Prego"
|
||||
"please_wait": "Attendere prego"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Velocità",
|
||||
@@ -391,17 +393,50 @@
|
||||
"cpuLoad": "Carico della CPU",
|
||||
"memoryUsed": "Memoria Utilizzata",
|
||||
"uptime": "Tempo di attività",
|
||||
"numberOfLeases": "Leases"
|
||||
"numberOfLeases": "Lease"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
"streams_all": "Tutti gli stream",
|
||||
"streams_active": "Stream attivi",
|
||||
"streams_xepg": "Canali XEPG"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"memory": "Active Memory",
|
||||
"cpu": "Carico CPU",
|
||||
"memory": "Memoria in uso",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Sunny",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"temp_bed": "Bed temp",
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
442
public/locales/lv/common.json
Normal file
442
public/locales/lv/common.json
Normal file
@@ -0,0 +1,442 @@
|
||||
{
|
||||
"common": {
|
||||
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||
},
|
||||
"widget": {
|
||||
"missing_type": "Iztrūkst logrīka tips: {{type}}",
|
||||
"api_error": "API kļūda",
|
||||
"information": "Informācija",
|
||||
"status": "Statuss",
|
||||
"url": "URL",
|
||||
"raw_error": "Kļūda",
|
||||
"response_data": "Atbilde"
|
||||
},
|
||||
"weather": {
|
||||
"current": "Pašreizējā atrašanās vieta",
|
||||
"allow": "Piemiedziet, lai atļaut",
|
||||
"updating": "Atjaunina",
|
||||
"wait": "Lūdzu, uzgaidiet"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Meklēt…"
|
||||
},
|
||||
"resources": {
|
||||
"cpu": "CPU",
|
||||
"total": "Kopā",
|
||||
"free": "Brīvs",
|
||||
"used": "Izmantojas",
|
||||
"load": "Ielādē"
|
||||
},
|
||||
"unifi": {
|
||||
"users": "Lietotāji",
|
||||
"uptime": "Sistēmas darbības laiks",
|
||||
"days": "Dienas",
|
||||
"wan": "WAN",
|
||||
"lan": "LAN",
|
||||
"wlan": "WLAN",
|
||||
"devices": "Ierīces",
|
||||
"lan_devices": "LAN ierīces",
|
||||
"wlan_devices": "WLAN ierīces",
|
||||
"lan_users": "LAN lietotāji",
|
||||
"wlan_users": "WLAN lietotāji",
|
||||
"up": "DARBOJAS",
|
||||
"down": "NEDARBOJAS",
|
||||
"wait": "Lūdzu, uzgaidiet"
|
||||
},
|
||||
"docker": {
|
||||
"rx": "RX",
|
||||
"tx": "TX",
|
||||
"mem": "Atmiņa",
|
||||
"cpu": "CPU",
|
||||
"offline": "Bezsaistē",
|
||||
"error": "Kļūda",
|
||||
"unknown": "Nezināms"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Kļūda",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "Atskaņo",
|
||||
"transcoding": "Pārkodē",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "Nav aktīvu straumju"
|
||||
},
|
||||
"flood": {
|
||||
"download": "Lejupielāde",
|
||||
"upload": "Augšupielāde",
|
||||
"leech": "Ņēmēji",
|
||||
"seed": "Devēji"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Kopā novēro",
|
||||
"diffsDetected": "Atšķirības atrastas"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Atskaņo",
|
||||
"transcoding": "Pārkodē",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "Nav aktīvu straumju"
|
||||
},
|
||||
"omada": {
|
||||
"connectedAp": "Savienotie piekļuves punkti",
|
||||
"activeUser": "Aktīvās ierīces",
|
||||
"alerts": "Paziņojumi",
|
||||
"connectedGateway": "Savienotās vārtejas",
|
||||
"connectedSwitches": "Savienotie komutatori"
|
||||
},
|
||||
"nzbget": {
|
||||
"rate": "Rate",
|
||||
"remaining": "Palika",
|
||||
"downloaded": "Lejupielādēts"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Aktīvās straumes",
|
||||
"movies": "Filmas",
|
||||
"tv": "TV pārraides"
|
||||
},
|
||||
"sabnzbd": {
|
||||
"rate": "Rate",
|
||||
"queue": "Rindā",
|
||||
"timeleft": "Atlikušais laiks"
|
||||
},
|
||||
"rutorrent": {
|
||||
"active": "Aktīvs",
|
||||
"upload": "Augšupielāde",
|
||||
"download": "Lejupielāde"
|
||||
},
|
||||
"transmission": {
|
||||
"download": "Lejupielāde",
|
||||
"upload": "Augšupielāde",
|
||||
"leech": "Leech",
|
||||
"seed": "Devēji"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Lejupielāde",
|
||||
"upload": "Augšupielāde",
|
||||
"leech": "Leech",
|
||||
"seed": "Devēji"
|
||||
},
|
||||
"deluge": {
|
||||
"download": "Lejupielāde",
|
||||
"upload": "Augšupielāde",
|
||||
"leech": "Leech",
|
||||
"seed": "Devēji"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
"upload": "Augšupielāde",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"radarr": {
|
||||
"wanted": "Wanted",
|
||||
"missing": "Missing",
|
||||
"queued": "Queued",
|
||||
"movies": "Filmas"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albumi"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"books": "Grāmatas"
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "Missing Episodes",
|
||||
"missingMovies": "Missing Movies"
|
||||
},
|
||||
"ombi": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
"processing": "Processing",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
},
|
||||
"pihole": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"gravity": "Gravity"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"filtered": "Filtered",
|
||||
"latency": "Latency"
|
||||
},
|
||||
"speedtest": {
|
||||
"upload": "Upload",
|
||||
"download": "Download",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"portainer": {
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"total": "Total"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Queue",
|
||||
"processed": "Processed",
|
||||
"errored": "Errored",
|
||||
"saved": "Saved"
|
||||
},
|
||||
"traefik": {
|
||||
"routers": "Routers",
|
||||
"services": "Services",
|
||||
"middleware": "Middleware"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
},
|
||||
"npm": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"total": "Total"
|
||||
},
|
||||
"coinmarketcap": {
|
||||
"configure": "Configure one or more crypto currencies to track",
|
||||
"1hour": "1 Hour",
|
||||
"1day": "1 Day",
|
||||
"7days": "7 Days",
|
||||
"30days": "30 Days"
|
||||
},
|
||||
"gotify": {
|
||||
"apps": "Applications",
|
||||
"clients": "Clients",
|
||||
"messages": "Messages"
|
||||
},
|
||||
"prowlarr": {
|
||||
"enableIndexers": "Indexers",
|
||||
"numberOfGrabs": "Grabs",
|
||||
"numberOfQueries": "Queries",
|
||||
"numberOfFailGrabs": "Fail Grabs",
|
||||
"numberOfFailQueries": "Fail Queries"
|
||||
},
|
||||
"jackett": {
|
||||
"configured": "Configured",
|
||||
"errored": "Errored"
|
||||
},
|
||||
"strelaysrv": {
|
||||
"numActiveSessions": "Sessions",
|
||||
"numConnections": "Connections",
|
||||
"dataRelayed": "Relayed",
|
||||
"transferRate": "Rate"
|
||||
},
|
||||
"mastodon": {
|
||||
"user_count": "Users",
|
||||
"status_count": "Posts",
|
||||
"domain_count": "Domains"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"cpu": "CPU",
|
||||
"lxc": "LXC",
|
||||
"vms": "VMs"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "CPU",
|
||||
"mem": "MEM",
|
||||
"wait": "Please wait"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Saulains",
|
||||
"0-night": "Skaidrs",
|
||||
"1-day": "Galvenokārt saulains",
|
||||
"1-night": "Galvenokārt skaidrs",
|
||||
"2-day": "Daļēji apmācies",
|
||||
"2-night": "Daļēji apmācies",
|
||||
"3-day": "Apmācies",
|
||||
"3-night": "Apmācies",
|
||||
"45-day": "Miglains",
|
||||
"45-night": "Miglains",
|
||||
"48-day": "Miglains",
|
||||
"48-night": "Miglains",
|
||||
"51-day": "Neliels lietus",
|
||||
"51-night": "Neliels lietus",
|
||||
"53-day": "Lietus",
|
||||
"53-night": "Lietus",
|
||||
"55-day": "Spēcīgs lietus",
|
||||
"55-night": "Spēcīgs lietus",
|
||||
"56-day": "Neliels stindzinošs lietus",
|
||||
"56-night": "Neliels stindzinošs lietus",
|
||||
"57-day": "Sasalstošs lietus",
|
||||
"57-night": "Freezing Drizzle",
|
||||
"61-day": "Viegls lietus",
|
||||
"61-night": "Viegls lietus",
|
||||
"63-day": "Lietus",
|
||||
"63-night": "Lietus",
|
||||
"65-day": "Spēcīgs lietus",
|
||||
"65-night": "Spēcīgs lietus",
|
||||
"66-day": "Ledains lietus",
|
||||
"66-night": "Ledains lietus",
|
||||
"67-day": "Ledains lietus",
|
||||
"67-night": "Ledains lietus",
|
||||
"71-day": "Neliels sniegs",
|
||||
"71-night": "Neliels sniegs",
|
||||
"73-day": "Sniegs",
|
||||
"73-night": "Sniegs",
|
||||
"75-day": "Heavy Snow",
|
||||
"75-night": "Heavy Snow",
|
||||
"77-day": "Snow Grains",
|
||||
"77-night": "Snow Grains",
|
||||
"80-day": "Light Showers",
|
||||
"80-night": "Light Showers",
|
||||
"81-day": "Showers",
|
||||
"81-night": "Showers",
|
||||
"82-day": "Heavy Showers",
|
||||
"82-night": "Heavy Showers",
|
||||
"85-day": "Snow Showers",
|
||||
"85-night": "Snow Showers",
|
||||
"86-day": "Snow Showers",
|
||||
"86-night": "Snow Showers",
|
||||
"95-day": "Thunderstorm",
|
||||
"95-night": "Thunderstorm",
|
||||
"96-day": "Thunderstorm With Hail",
|
||||
"96-night": "Thunderstorm With Hail",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
"updates": "Updates",
|
||||
"update_available": "Update Available",
|
||||
"up_to_date": "Up to Date",
|
||||
"child_bridges": "Child Bridges",
|
||||
"child_bridges_status": "{{ok}}/{{total}}"
|
||||
},
|
||||
"watchtower": {
|
||||
"containers_scanned": "Scanned",
|
||||
"containers_updated": "Updated",
|
||||
"containers_failed": "Failed"
|
||||
},
|
||||
"autobrr": {
|
||||
"approvedPushes": "Approved",
|
||||
"rejectedPushes": "Rejected",
|
||||
"filters": "Filters",
|
||||
"indexers": "Indexers"
|
||||
},
|
||||
"tubearchivist": {
|
||||
"downloads": "Queue",
|
||||
"videos": "Videos",
|
||||
"channels": "Channels",
|
||||
"playlists": "Playlists"
|
||||
},
|
||||
"truenas": {
|
||||
"load": "System Load",
|
||||
"uptime": "Uptime",
|
||||
"alerts": "Alerts",
|
||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
"active": "Active",
|
||||
"queue": "Queue",
|
||||
"total": "Total"
|
||||
},
|
||||
"gluetun": {
|
||||
"public_ip": "Public IP",
|
||||
"region": "Region",
|
||||
"country": "Country"
|
||||
},
|
||||
"hdhomerun": {
|
||||
"channels": "Channels",
|
||||
"hd": "HD"
|
||||
},
|
||||
"scrutiny": {
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"paperlessngx": {
|
||||
"inbox": "Inbox",
|
||||
"total": "Total"
|
||||
},
|
||||
"nextdns": {
|
||||
"wait": "Please Wait",
|
||||
"no_devices": "No Device Data Received"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
"memoryUsed": "Memory Used",
|
||||
"uptime": "Uptime",
|
||||
"numberOfLeases": "Leases"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Tandabuku",
|
||||
"service": "Servis"
|
||||
"service": "Servis",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Terik",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
"missing_type": "Missing Widget Type: {{type}}",
|
||||
"api_error": "API Error",
|
||||
"status": "Status",
|
||||
"information": "Information",
|
||||
"information": "Informatie",
|
||||
"url": "URL",
|
||||
"raw_error": "Raw Error",
|
||||
"response_data": "Response Data"
|
||||
"raw_error": "Raw Fout",
|
||||
"response_data": "Reactiegegevens"
|
||||
},
|
||||
"resources": {
|
||||
"total": "Totaal",
|
||||
"free": "Vrij",
|
||||
"used": "Gebruikt",
|
||||
"load": "Load",
|
||||
"load": "Laadt",
|
||||
"cpu": "CPU"
|
||||
},
|
||||
"docker": {
|
||||
@@ -21,8 +21,8 @@
|
||||
"mem": "MEM",
|
||||
"cpu": "CPU",
|
||||
"offline": "Offline",
|
||||
"error": "Error",
|
||||
"unknown": "Unknown"
|
||||
"error": "Fout",
|
||||
"unknown": "Onbekend"
|
||||
},
|
||||
"speedtest": {
|
||||
"upload": "Upload",
|
||||
@@ -190,20 +190,20 @@
|
||||
"vms": "VMs"
|
||||
},
|
||||
"unifi": {
|
||||
"users": "Users",
|
||||
"lan_users": "LAN Users",
|
||||
"uptime": "System Uptime",
|
||||
"days": "Days",
|
||||
"users": "Gebruikers",
|
||||
"lan_users": "LAN Gebruikers",
|
||||
"uptime": "Uptime van het systeem",
|
||||
"days": "Dagen",
|
||||
"wan": "WAN",
|
||||
"wlan_users": "WLAN Users",
|
||||
"wlan_users": "WLAN Gebruikers",
|
||||
"up": "UP",
|
||||
"down": "DOWN",
|
||||
"wait": "Please wait",
|
||||
"wait": "Wachten aub",
|
||||
"lan": "LAN",
|
||||
"wlan": "WLAN",
|
||||
"devices": "Devices",
|
||||
"lan_devices": "LAN Devices",
|
||||
"wlan_devices": "WLAN Devices"
|
||||
"devices": "Apparaten",
|
||||
"lan_devices": "LAN Apparaten",
|
||||
"wlan_devices": "WLAN Apparaten"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Active Streams",
|
||||
@@ -216,7 +216,7 @@
|
||||
"wait": "Please wait"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
"totalObserved": "Totaal waargenomen",
|
||||
"diffsDetected": "Diffs Detected"
|
||||
},
|
||||
"wmo": {
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -332,7 +334,7 @@
|
||||
"hd": "HD"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "Fout",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"scrutiny": {
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Zakładka",
|
||||
"service": "Usługi"
|
||||
"service": "Usługi",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -394,14 +396,47 @@
|
||||
"numberOfLeases": "Dzierżawy"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
"streams_all": "Wszystkie strumienie",
|
||||
"streams_active": "Aktywne strumienie",
|
||||
"streams_xepg": "Kanały XEPG"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
"cpu": "Obciążenie procesora",
|
||||
"memory": "Pamięć rzeczywista",
|
||||
"wanUpload": "WAN wysyłanie",
|
||||
"wanDownload": "WAN pobieranie"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Stan drukarki",
|
||||
"print_status": "Status wydruku",
|
||||
"print_progress": "Postęp",
|
||||
"layers": "Warstwy"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Poszukiwane",
|
||||
"queued": "Zakolejkowane",
|
||||
"series": "Seria"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
"missing_type": "Tipo de Widget ausente: {{type}}",
|
||||
"api_error": "Erro da API",
|
||||
"status": "Status",
|
||||
"information": "Information",
|
||||
"information": "Informação",
|
||||
"url": "URL",
|
||||
"raw_error": "Raw Error",
|
||||
"response_data": "Response Data"
|
||||
"response_data": "Dados de Resposta"
|
||||
},
|
||||
"weather": {
|
||||
"current": "Localização atual",
|
||||
@@ -53,13 +53,13 @@
|
||||
"cpu": "CPU"
|
||||
},
|
||||
"docker": {
|
||||
"rx": "Rx",
|
||||
"tx": "Tx",
|
||||
"mem": "Mem",
|
||||
"rx": "Recebido",
|
||||
"tx": "Transmitido",
|
||||
"mem": "Memória",
|
||||
"cpu": "CPU",
|
||||
"offline": "Desligado",
|
||||
"error": "Error",
|
||||
"unknown": "Unknown"
|
||||
"error": "Erro",
|
||||
"unknown": "Desconhecido"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "Reproduzindo",
|
||||
@@ -99,7 +99,7 @@
|
||||
"wanted": "Desejado",
|
||||
"queued": "Na fila",
|
||||
"movies": "Filmes",
|
||||
"missing": "Missing"
|
||||
"missing": "Faltando"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Desejado",
|
||||
@@ -129,7 +129,7 @@
|
||||
"pending": "Pendente",
|
||||
"approved": "Aprovado",
|
||||
"available": "Disponível",
|
||||
"processing": "Processing"
|
||||
"processing": "Processando"
|
||||
},
|
||||
"pihole": {
|
||||
"queries": "Consultas",
|
||||
@@ -148,9 +148,9 @@
|
||||
"ping": "Ping"
|
||||
},
|
||||
"traefik": {
|
||||
"routers": "Rotas",
|
||||
"routers": "Roteadores",
|
||||
"services": "Serviços",
|
||||
"middleware": "Middleware"
|
||||
"middleware": "Software intermediario"
|
||||
},
|
||||
"npm": {
|
||||
"enabled": "Habilitado",
|
||||
@@ -164,10 +164,10 @@
|
||||
},
|
||||
"prowlarr": {
|
||||
"enableIndexers": "Indexadores",
|
||||
"numberOfGrabs": "Grabs",
|
||||
"numberOfQueries": "Queries",
|
||||
"numberOfGrabs": "Pegos",
|
||||
"numberOfQueries": "Consultas",
|
||||
"numberOfFailGrabs": "Fail Grabs",
|
||||
"numberOfFailQueries": "Fail Queries"
|
||||
"numberOfFailQueries": "Consultas Falhas"
|
||||
},
|
||||
"jackett": {
|
||||
"configured": "Configurado",
|
||||
@@ -179,36 +179,36 @@
|
||||
"domain_count": "Domínios"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"users": "Usuários",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"cpu": "CPU",
|
||||
"mem": "Memória",
|
||||
"cpu": "Processador",
|
||||
"lxc": "LXC",
|
||||
"vms": "VMs"
|
||||
},
|
||||
"unifi": {
|
||||
"users": "Users",
|
||||
"uptime": "System Uptime",
|
||||
"days": "Days",
|
||||
"users": "Usuários",
|
||||
"uptime": "Tempo de Funcionamento",
|
||||
"days": "Dias",
|
||||
"wan": "WAN",
|
||||
"lan_users": "LAN Users",
|
||||
"wlan_users": "WLAN Users",
|
||||
"up": "UP",
|
||||
"down": "DOWN",
|
||||
"wait": "Please wait",
|
||||
"lan_users": "Usuarios locais",
|
||||
"wlan_users": "Usuarios WLAN",
|
||||
"up": "LIGADO",
|
||||
"down": "CÁIDO",
|
||||
"wait": "Por favor guarde",
|
||||
"lan": "LAN",
|
||||
"wlan": "WLAN",
|
||||
"devices": "Devices",
|
||||
"lan_devices": "LAN Devices",
|
||||
"wlan_devices": "WLAN Devices"
|
||||
"devices": "Dispositivos",
|
||||
"lan_devices": "Dispositivos LAN",
|
||||
"wlan_devices": "Dispositivos WLAN"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Active Streams",
|
||||
"movies": "Movies",
|
||||
"tv": "TV Shows"
|
||||
"streams": "Transmissões ativas",
|
||||
"movies": "Filmes",
|
||||
"tv": "Séries de TV"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "CPU",
|
||||
@@ -222,10 +222,10 @@
|
||||
"wmo": {
|
||||
"1-night": "Mainly Clear",
|
||||
"2-day": "Partly Cloudy",
|
||||
"2-night": "Partly Cloudy",
|
||||
"3-day": "Cloudy",
|
||||
"3-night": "Cloudy",
|
||||
"45-day": "Foggy",
|
||||
"2-night": "Parcialmente nublado",
|
||||
"3-day": "Nublado",
|
||||
"3-night": "Nublado",
|
||||
"45-day": "Névoa",
|
||||
"45-night": "Foggy",
|
||||
"48-day": "Foggy",
|
||||
"48-night": "Foggy",
|
||||
@@ -233,9 +233,9 @@
|
||||
"57-day": "Freezing Drizzle",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail",
|
||||
"0-day": "Sunny",
|
||||
"0-day": "Ensolarado",
|
||||
"53-day": "Drizzle",
|
||||
"0-night": "Clear",
|
||||
"0-night": "Limpo",
|
||||
"1-day": "Mainly Sunny",
|
||||
"51-day": "Light Drizzle",
|
||||
"51-night": "Light Drizzle",
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -313,8 +315,8 @@
|
||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
"nothing_streaming": "Sem transmissões ativas",
|
||||
"please_wait": "Por favor aguarde"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
@@ -332,7 +334,7 @@
|
||||
"hd": "HD"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "Erro",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"scrutiny": {
|
||||
@@ -357,14 +359,14 @@
|
||||
"seed": "Seed"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Queue",
|
||||
"processed": "Processed",
|
||||
"errored": "Errored",
|
||||
"saved": "Saved"
|
||||
"queue": "Fila",
|
||||
"processed": "Processado",
|
||||
"errored": "Erro",
|
||||
"saved": "Salvo"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
"read": "Lidos",
|
||||
"unread": "Não Lidos"
|
||||
},
|
||||
"nextdns": {
|
||||
"wait": "Please Wait",
|
||||
@@ -375,11 +377,11 @@
|
||||
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||
},
|
||||
"omada": {
|
||||
"connectedAp": "Connected APs",
|
||||
"activeUser": "Active devices",
|
||||
"alerts": "Alerts",
|
||||
"connectedGateway": "Connected gateways",
|
||||
"connectedSwitches": "Connected switches"
|
||||
"connectedAp": "Pontos de acesso conectados",
|
||||
"activeUser": "Dispositivos ativos",
|
||||
"alerts": "Alertas",
|
||||
"connectedGateway": "Gateways conectados",
|
||||
"connectedSwitches": "Interruptores conectados"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +292,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Marcador",
|
||||
"service": "Serviço"
|
||||
"service": "Serviço",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sistema",
|
||||
@@ -412,5 +414,38 @@
|
||||
"memory": "Memória Ativa",
|
||||
"wanUpload": "Envio WAN",
|
||||
"wanDownload": "WAN Descarga"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"update_available": "Update Available",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"print_progress": "Progress",
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "బుక్మార్క్",
|
||||
"service": "సేవ"
|
||||
"service": "సేవ",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "వ్యవస్థ",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Yer İmi",
|
||||
"service": "Hizmet"
|
||||
"service": "Hizmet",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "Sistem",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
"deluge": {
|
||||
"download": "Завантаження",
|
||||
"upload": "Відправлення",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Ліч",
|
||||
"seed": "Сід"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Розшукується",
|
||||
@@ -32,76 +32,76 @@
|
||||
"books": "Книжки"
|
||||
},
|
||||
"wmo": {
|
||||
"55-day": "Heavy Drizzle",
|
||||
"55-night": "Heavy Drizzle",
|
||||
"56-day": "Light Freezing Drizzle",
|
||||
"56-night": "Light Freezing Drizzle",
|
||||
"0-day": "Sunny",
|
||||
"0-night": "Clear",
|
||||
"1-day": "Mainly Sunny",
|
||||
"1-night": "Mainly Clear",
|
||||
"2-day": "Partly Cloudy",
|
||||
"2-night": "Partly Cloudy",
|
||||
"3-day": "Cloudy",
|
||||
"3-night": "Cloudy",
|
||||
"53-day": "Drizzle",
|
||||
"45-day": "Foggy",
|
||||
"45-night": "Foggy",
|
||||
"48-day": "Foggy",
|
||||
"48-night": "Foggy",
|
||||
"51-day": "Light Drizzle",
|
||||
"51-night": "Light Drizzle",
|
||||
"53-night": "Drizzle",
|
||||
"57-day": "Freezing Drizzle",
|
||||
"57-night": "Freezing Drizzle",
|
||||
"61-day": "Light Rain",
|
||||
"61-night": "Light Rain",
|
||||
"63-day": "Rain",
|
||||
"63-night": "Rain",
|
||||
"65-day": "Heavy Rain",
|
||||
"65-night": "Heavy Rain",
|
||||
"66-day": "Freezing Rain",
|
||||
"66-night": "Freezing Rain",
|
||||
"67-day": "Freezing Rain",
|
||||
"67-night": "Freezing Rain",
|
||||
"71-day": "Light Snow",
|
||||
"71-night": "Light Snow",
|
||||
"73-day": "Snow",
|
||||
"73-night": "Snow",
|
||||
"75-day": "Heavy Snow",
|
||||
"75-night": "Heavy Snow",
|
||||
"77-day": "Snow Grains",
|
||||
"77-night": "Snow Grains",
|
||||
"80-day": "Light Showers",
|
||||
"80-night": "Light Showers",
|
||||
"81-day": "Showers",
|
||||
"82-day": "Heavy Showers",
|
||||
"82-night": "Heavy Showers",
|
||||
"81-night": "Showers",
|
||||
"85-day": "Snow Showers",
|
||||
"85-night": "Snow Showers",
|
||||
"86-day": "Snow Showers",
|
||||
"86-night": "Snow Showers",
|
||||
"95-day": "Thunderstorm",
|
||||
"95-night": "Thunderstorm",
|
||||
"96-day": "Thunderstorm With Hail",
|
||||
"96-night": "Thunderstorm With Hail",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail"
|
||||
"55-day": "Сильна мряка",
|
||||
"55-night": "Сильна мряка",
|
||||
"56-day": "Невеликий морозний дощ",
|
||||
"56-night": "Невеликий морозний дощ",
|
||||
"0-day": "Сонячно",
|
||||
"0-night": "Ясно",
|
||||
"1-day": "Переважно сонячно",
|
||||
"1-night": "Переважно ясно",
|
||||
"2-day": "Частково хмарно",
|
||||
"2-night": "Частково хмарно",
|
||||
"3-day": "Хмарно",
|
||||
"3-night": "Хмарно",
|
||||
"53-day": "Мряка",
|
||||
"45-day": "Туманно",
|
||||
"45-night": "Туманно",
|
||||
"48-day": "Туманно",
|
||||
"48-night": "Туманно",
|
||||
"51-day": "Легка мряка",
|
||||
"51-night": "Легка мряка",
|
||||
"53-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": "Злива",
|
||||
"82-day": "Сильна злива",
|
||||
"82-night": "Сильна злива",
|
||||
"81-night": "Злива",
|
||||
"85-day": "Дощ зі снігом",
|
||||
"85-night": "Дощ зі снігом",
|
||||
"86-day": "Дощ зі снігом",
|
||||
"86-night": "Дощ зі снігом",
|
||||
"95-day": "Гроза",
|
||||
"95-night": "Гроза",
|
||||
"96-day": "Гроза з градом",
|
||||
"96-night": "Гроза з градом",
|
||||
"99-day": "Гроза з градом",
|
||||
"99-night": "Гроза з градом"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
"active": "Active",
|
||||
"queue": "Queue",
|
||||
"total": "Total"
|
||||
"speed": "Швидкість",
|
||||
"active": "Активно",
|
||||
"queue": "Черга",
|
||||
"total": "Всього"
|
||||
},
|
||||
"gluetun": {
|
||||
"country": "Country",
|
||||
"public_ip": "Public IP",
|
||||
"region": "Region"
|
||||
"country": "Країна",
|
||||
"public_ip": "Публічний IP",
|
||||
"region": "Регіон"
|
||||
},
|
||||
"hdhomerun": {
|
||||
"channels": "Channels",
|
||||
"channels": "Канали",
|
||||
"hd": "HD"
|
||||
},
|
||||
"widget": {
|
||||
@@ -167,8 +167,8 @@
|
||||
"flood": {
|
||||
"download": "Завантаження",
|
||||
"upload": "Відправлення",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Ліч",
|
||||
"seed": "Сід"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Всього спостережень",
|
||||
@@ -193,20 +193,20 @@
|
||||
"transmission": {
|
||||
"download": "Завантаження",
|
||||
"upload": "Відправлення",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Ліч",
|
||||
"seed": "Сід"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Завантаження",
|
||||
"upload": "Відправлення",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Ліч",
|
||||
"seed": "Сід"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Завантаження",
|
||||
"upload": "Відправлення",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"leech": "Ліч",
|
||||
"seed": "Сід"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Розшукується",
|
||||
@@ -225,13 +225,13 @@
|
||||
"albums": "Альбоми"
|
||||
},
|
||||
"traefik": {
|
||||
"middleware": "Middleware",
|
||||
"middleware": "Проміжне програмне забезпечення",
|
||||
"routers": "Роутери",
|
||||
"services": "Сервіси"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
"nothing_streaming": "Немає активних потоків",
|
||||
"please_wait": "Будь ласка, зачекайте"
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "Відсутні епізоди",
|
||||
@@ -281,127 +281,162 @@
|
||||
"saved": "Збережено"
|
||||
},
|
||||
"npm": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"total": "Total"
|
||||
"enabled": "Увімкнено",
|
||||
"disabled": "Вимкнено",
|
||||
"total": "Всього"
|
||||
},
|
||||
"coinmarketcap": {
|
||||
"configure": "Configure one or more crypto currencies to track",
|
||||
"1hour": "1 Hour",
|
||||
"1day": "1 Day",
|
||||
"7days": "7 Days",
|
||||
"30days": "30 Days"
|
||||
"configure": "Налаштуйте одну або кілька криптовалют для відстеження",
|
||||
"1hour": "1 година",
|
||||
"1day": "1 день",
|
||||
"7days": "7 днів",
|
||||
"30days": "30 днів"
|
||||
},
|
||||
"mastodon": {
|
||||
"domain_count": "Domains",
|
||||
"user_count": "Users",
|
||||
"status_count": "Posts"
|
||||
"domain_count": "Домени",
|
||||
"user_count": "Користувачі",
|
||||
"status_count": "Пости"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
"read": "Прочитано",
|
||||
"unread": "Не прочитано"
|
||||
},
|
||||
"gotify": {
|
||||
"apps": "Applications",
|
||||
"clients": "Clients",
|
||||
"messages": "Messages"
|
||||
"apps": "Застосунки",
|
||||
"clients": "Клієнти",
|
||||
"messages": "Повідомлення"
|
||||
},
|
||||
"prowlarr": {
|
||||
"enableIndexers": "Indexers",
|
||||
"numberOfGrabs": "Grabs",
|
||||
"numberOfQueries": "Queries",
|
||||
"numberOfFailGrabs": "Fail Grabs",
|
||||
"numberOfFailQueries": "Fail Queries"
|
||||
"enableIndexers": "Індексатори",
|
||||
"numberOfGrabs": "Захоплення",
|
||||
"numberOfQueries": "Запити",
|
||||
"numberOfFailGrabs": "Невдалі захоплення",
|
||||
"numberOfFailQueries": "Невдалі запити"
|
||||
},
|
||||
"jackett": {
|
||||
"configured": "Configured",
|
||||
"errored": "Errored"
|
||||
"configured": "Налаштовано",
|
||||
"errored": "Помилка"
|
||||
},
|
||||
"strelaysrv": {
|
||||
"numActiveSessions": "Sessions",
|
||||
"numConnections": "Connections",
|
||||
"dataRelayed": "Relayed",
|
||||
"transferRate": "Rate"
|
||||
"numActiveSessions": "Сесії",
|
||||
"numConnections": "Підключення",
|
||||
"dataRelayed": "Ретрансльовано",
|
||||
"transferRate": "Швидкість"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
"users": "Користувачі",
|
||||
"loginsLast24H": "Вхід (24 години)",
|
||||
"failedLoginsLast24H": "Невдалі входи (24 години)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"mem": "Пам'ять",
|
||||
"cpu": "CPU",
|
||||
"vms": "VMs",
|
||||
"lxc": "LXC"
|
||||
"vms": "Віртуальні машини",
|
||||
"lxc": "Контейнери Linux"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "CPU",
|
||||
"mem": "MEM",
|
||||
"wait": "Please wait"
|
||||
"mem": "Пам'ять",
|
||||
"wait": "Будь ласка, зачекайте"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"bookmark": "Закладка",
|
||||
"service": "Сервіс",
|
||||
"search": "Пошук",
|
||||
"custom": "Користувацький"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
"updates": "Updates",
|
||||
"available_update": "Система",
|
||||
"updates": "Оновлення",
|
||||
"child_bridges_status": "{{ok}}/{{total}}",
|
||||
"update_available": "Update Available",
|
||||
"up_to_date": "Up to Date",
|
||||
"child_bridges": "Child Bridges"
|
||||
"update_available": "Доступне оновлення",
|
||||
"up_to_date": "Актуально",
|
||||
"child_bridges": "Дитячі мости"
|
||||
},
|
||||
"watchtower": {
|
||||
"containers_scanned": "Scanned",
|
||||
"containers_updated": "Updated",
|
||||
"containers_failed": "Failed"
|
||||
"containers_scanned": "Відскановано",
|
||||
"containers_updated": "Оновлено",
|
||||
"containers_failed": "Невдача"
|
||||
},
|
||||
"autobrr": {
|
||||
"approvedPushes": "Approved",
|
||||
"rejectedPushes": "Rejected",
|
||||
"filters": "Filters",
|
||||
"indexers": "Indexers"
|
||||
"approvedPushes": "Схвалено",
|
||||
"rejectedPushes": "Відхилено",
|
||||
"filters": "Фільтри",
|
||||
"indexers": "Індексатори"
|
||||
},
|
||||
"tubearchivist": {
|
||||
"downloads": "Queue",
|
||||
"videos": "Videos",
|
||||
"channels": "Channels",
|
||||
"playlists": "Playlists"
|
||||
"downloads": "Черга",
|
||||
"videos": "Відео",
|
||||
"channels": "Канали",
|
||||
"playlists": "Плейлисти"
|
||||
},
|
||||
"truenas": {
|
||||
"load": "System Load",
|
||||
"uptime": "Uptime",
|
||||
"alerts": "Alerts",
|
||||
"load": "Завантаження системи",
|
||||
"uptime": "Час роботи",
|
||||
"alerts": "Сповіщення",
|
||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||
},
|
||||
"scrutiny": {
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"unknown": "Unknown"
|
||||
"passed": "Пройшов",
|
||||
"failed": "Невдача",
|
||||
"unknown": "Невідомо"
|
||||
},
|
||||
"paperlessngx": {
|
||||
"inbox": "Inbox",
|
||||
"total": "Total"
|
||||
"inbox": "Вхідні",
|
||||
"total": "Всього"
|
||||
},
|
||||
"nextdns": {
|
||||
"wait": "Please Wait",
|
||||
"no_devices": "No Device Data Received"
|
||||
"wait": "Будь ласка, зачекайте",
|
||||
"no_devices": "Дані про пристрій не отримано"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
"memoryUsed": "Memory Used",
|
||||
"uptime": "Uptime",
|
||||
"numberOfLeases": "Leases"
|
||||
"cpuLoad": "Завантаження CPU",
|
||||
"memoryUsed": "Використана пам'ять",
|
||||
"uptime": "Час роботи",
|
||||
"numberOfLeases": "Оренди"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
"streams_all": "Всі потоки",
|
||||
"streams_active": "Активні потоки",
|
||||
"streams_xepg": "Канали XEPG"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
"cpu": "Завантаження CPU",
|
||||
"memory": "Активна пам'ять",
|
||||
"wanUpload": "Вивантаження WAN",
|
||||
"wanDownload": "Завантаження WAN"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Стан принтера",
|
||||
"print_status": "Статус друку",
|
||||
"print_progress": "Прогрес",
|
||||
"layers": "Шари"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Розшукується",
|
||||
"queued": "У черзі",
|
||||
"series": "Серії"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Стан",
|
||||
"temp_tool": "Температура інструменту",
|
||||
"temp_bed": "Температура ліжка",
|
||||
"job_completion": "Завершення"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Походження IP",
|
||||
"status": "Стан"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Сховище даних",
|
||||
"failed_tasks_24h": "Невиконані завдання 24 години",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Пам'ять"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Користувачі",
|
||||
"photos": "Фотографії",
|
||||
"videos": "Відео",
|
||||
"storage": "Сховище"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"service": "Service",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers",
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
"missing_type": "缺少小部件类型:{{type}}",
|
||||
"api_error": "API错误",
|
||||
"status": "状态",
|
||||
"information": "Information",
|
||||
"information": "信息",
|
||||
"url": "URL",
|
||||
"raw_error": "Raw Error",
|
||||
"response_data": "Response Data"
|
||||
"raw_error": "原始错误",
|
||||
"response_data": "返回数据"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "搜索…"
|
||||
},
|
||||
"resources": {
|
||||
"total": "共",
|
||||
"total": "总计",
|
||||
"free": "空闲",
|
||||
"used": "已用",
|
||||
"load": "负载",
|
||||
@@ -24,8 +24,8 @@
|
||||
"mem": "内存",
|
||||
"cpu": "处理器",
|
||||
"offline": "离线",
|
||||
"error": "Error",
|
||||
"unknown": "Unknown"
|
||||
"error": "错误",
|
||||
"unknown": "未知"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "播放中",
|
||||
@@ -279,7 +279,9 @@
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "书签",
|
||||
"service": "服务"
|
||||
"service": "服务",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
@@ -332,7 +334,7 @@
|
||||
"hd": "HD"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "错误",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"scrutiny": {
|
||||
@@ -345,22 +347,22 @@
|
||||
"total": "Total"
|
||||
},
|
||||
"deluge": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下载",
|
||||
"upload": "上传",
|
||||
"leech": "下载中",
|
||||
"seed": "做种"
|
||||
},
|
||||
"flood": {
|
||||
"leech": "Leech",
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"seed": "Seed"
|
||||
"leech": "下载中",
|
||||
"download": "下载",
|
||||
"upload": "上传",
|
||||
"seed": "做种"
|
||||
},
|
||||
"tdarr": {
|
||||
"saved": "Saved",
|
||||
"queue": "Queue",
|
||||
"queue": "队列",
|
||||
"processed": "Processed",
|
||||
"errored": "Errored"
|
||||
"errored": "出错"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
@@ -376,16 +378,16 @@
|
||||
},
|
||||
"omada": {
|
||||
"connectedAp": "Connected APs",
|
||||
"activeUser": "Active devices",
|
||||
"alerts": "Alerts",
|
||||
"connectedGateway": "Connected gateways",
|
||||
"connectedSwitches": "Connected switches"
|
||||
"activeUser": "活跃设备",
|
||||
"alerts": "警报",
|
||||
"connectedGateway": "已连接网关",
|
||||
"connectedSwitches": "已连接开关"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下载",
|
||||
"upload": "上传",
|
||||
"leech": "下载中",
|
||||
"seed": "做种"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
@@ -403,5 +405,38 @@
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "Printer State",
|
||||
"print_status": "Print Status",
|
||||
"print_progress": "Progress",
|
||||
"layers": "Layers"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "Status",
|
||||
"temp_tool": "Tool temp",
|
||||
"temp_bed": "Bed temp",
|
||||
"job_completion": "Completion"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,407 +1,442 @@
|
||||
{
|
||||
"widget": {
|
||||
"missing_type": "Missing Widget Type: {{type}}",
|
||||
"api_error": "API Error",
|
||||
"status": "Status",
|
||||
"information": "Information",
|
||||
"missing_type": "遺失小工具的類型: {{type}}",
|
||||
"api_error": "API錯誤",
|
||||
"status": "狀態",
|
||||
"information": "資訊",
|
||||
"url": "URL",
|
||||
"raw_error": "Raw Error",
|
||||
"response_data": "Response Data"
|
||||
},
|
||||
"weather": {
|
||||
"current": "Current Location",
|
||||
"allow": "Click to allow",
|
||||
"updating": "Updating",
|
||||
"wait": "Please wait"
|
||||
"current": "目前位置",
|
||||
"allow": "點擊以允許",
|
||||
"updating": "更新中",
|
||||
"wait": "請稍後"
|
||||
},
|
||||
"docker": {
|
||||
"rx": "RX",
|
||||
"offline": "Offline",
|
||||
"tx": "TX",
|
||||
"mem": "MEM",
|
||||
"cpu": "CPU",
|
||||
"error": "Error",
|
||||
"unknown": "Unknown"
|
||||
"rx": "接收",
|
||||
"offline": "離線",
|
||||
"tx": "發送",
|
||||
"mem": "記憶體",
|
||||
"cpu": "處理器",
|
||||
"error": "錯誤",
|
||||
"unknown": "未知的"
|
||||
},
|
||||
"emby": {
|
||||
"playing": "Playing",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "No Active Streams"
|
||||
"playing": "正在播放",
|
||||
"transcoding": "轉碼",
|
||||
"bitrate": "位元率",
|
||||
"no_active": "無播放活動"
|
||||
},
|
||||
"tautulli": {
|
||||
"playing": "Playing",
|
||||
"transcoding": "Transcoding",
|
||||
"bitrate": "Bitrate",
|
||||
"no_active": "No Active Streams"
|
||||
"playing": "正在播放",
|
||||
"transcoding": "轉碼",
|
||||
"bitrate": "位元率",
|
||||
"no_active": "無播放活動"
|
||||
},
|
||||
"jellyseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "待定",
|
||||
"approved": "已接受",
|
||||
"available": "可用的"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Search…"
|
||||
"placeholder": "搜尋…"
|
||||
},
|
||||
"resources": {
|
||||
"total": "Total",
|
||||
"free": "Free",
|
||||
"used": "Used",
|
||||
"load": "Load",
|
||||
"total": "全部",
|
||||
"free": "剩餘",
|
||||
"used": "已使用",
|
||||
"load": "負載",
|
||||
"cpu": "CPU"
|
||||
},
|
||||
"nzbget": {
|
||||
"rate": "Rate",
|
||||
"remaining": "Remaining",
|
||||
"downloaded": "Downloaded"
|
||||
"rate": "速率",
|
||||
"remaining": "剩餘",
|
||||
"downloaded": "已下載"
|
||||
},
|
||||
"sabnzbd": {
|
||||
"rate": "Rate",
|
||||
"queue": "Queue",
|
||||
"timeleft": "Time Left"
|
||||
"rate": "速率",
|
||||
"queue": "佇列",
|
||||
"timeleft": "剩餘時間"
|
||||
},
|
||||
"rutorrent": {
|
||||
"active": "Active",
|
||||
"upload": "Upload",
|
||||
"download": "Download"
|
||||
"active": "活動中",
|
||||
"upload": "上行速率",
|
||||
"download": "下行速率"
|
||||
},
|
||||
"radarr": {
|
||||
"movies": "Movies",
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"missing": "Missing"
|
||||
"movies": "電影",
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"missing": "缺少"
|
||||
},
|
||||
"sonarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"series": "Series"
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"series": "影集"
|
||||
},
|
||||
"readarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"books": "Books"
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"books": "書籍"
|
||||
},
|
||||
"ombi": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available"
|
||||
"pending": "待定",
|
||||
"approved": "已接受",
|
||||
"available": "可用的"
|
||||
},
|
||||
"overseerr": {
|
||||
"pending": "Pending",
|
||||
"approved": "Approved",
|
||||
"available": "Available",
|
||||
"processing": "Processing"
|
||||
"pending": "待定",
|
||||
"approved": "已接受",
|
||||
"available": "可用的",
|
||||
"processing": "處理中"
|
||||
},
|
||||
"pihole": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"queries": "查詢",
|
||||
"blocked": "已阻擋",
|
||||
"gravity": "Gravity"
|
||||
},
|
||||
"speedtest": {
|
||||
"upload": "Upload",
|
||||
"download": "Download",
|
||||
"upload": "上行速率",
|
||||
"download": "下行速率",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"portainer": {
|
||||
"running": "Running",
|
||||
"stopped": "Stopped",
|
||||
"total": "Total"
|
||||
"running": "運行中",
|
||||
"stopped": "未運行",
|
||||
"total": "全部"
|
||||
},
|
||||
"traefik": {
|
||||
"routers": "Routers",
|
||||
"services": "Services",
|
||||
"middleware": "Middleware"
|
||||
"routers": "路由器",
|
||||
"services": "服務",
|
||||
"middleware": "中介軟體"
|
||||
},
|
||||
"gotify": {
|
||||
"clients": "Clients",
|
||||
"apps": "Applications",
|
||||
"messages": "Messages"
|
||||
"clients": "客戶端",
|
||||
"apps": "應用程式",
|
||||
"messages": "訊息"
|
||||
},
|
||||
"npm": {
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"total": "Total"
|
||||
"enabled": "已啟用",
|
||||
"disabled": "已停用",
|
||||
"total": "全部"
|
||||
},
|
||||
"coinmarketcap": {
|
||||
"configure": "Configure one or more crypto currencies to track",
|
||||
"1hour": "1 Hour",
|
||||
"1day": "1 Day",
|
||||
"7days": "7 Days",
|
||||
"30days": "30 Days"
|
||||
"configure": "請設定一個或多個欲追蹤的加密貨幣",
|
||||
"1hour": "1小時",
|
||||
"1day": "1天",
|
||||
"7days": "7天",
|
||||
"30days": "30天"
|
||||
},
|
||||
"prowlarr": {
|
||||
"enableIndexers": "Indexers",
|
||||
"numberOfGrabs": "Grabs",
|
||||
"numberOfQueries": "Queries",
|
||||
"numberOfFailGrabs": "Fail Grabs",
|
||||
"numberOfFailQueries": "Fail Queries"
|
||||
"enableIndexers": "索引器",
|
||||
"numberOfGrabs": "抓取",
|
||||
"numberOfQueries": "查詢",
|
||||
"numberOfFailGrabs": "抓取失敗",
|
||||
"numberOfFailQueries": "查詢失敗"
|
||||
},
|
||||
"transmission": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下行速率",
|
||||
"upload": "上行速率",
|
||||
"leech": "未完成下載",
|
||||
"seed": "已完成下載"
|
||||
},
|
||||
"jackett": {
|
||||
"configured": "Configured",
|
||||
"errored": "Errored"
|
||||
"configured": "已配置",
|
||||
"errored": "發生錯誤"
|
||||
},
|
||||
"bazarr": {
|
||||
"missingEpisodes": "Missing Episodes",
|
||||
"missingMovies": "Missing Movies"
|
||||
"missingEpisodes": "缺少的劇集",
|
||||
"missingMovies": "缺少的電影"
|
||||
},
|
||||
"lidarr": {
|
||||
"wanted": "Wanted",
|
||||
"queued": "Queued",
|
||||
"albums": "Albums"
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"albums": "專輯"
|
||||
},
|
||||
"adguard": {
|
||||
"queries": "Queries",
|
||||
"blocked": "Blocked",
|
||||
"filtered": "Filtered",
|
||||
"latency": "Latency"
|
||||
"queries": "查詢",
|
||||
"blocked": "已阻擋",
|
||||
"filtered": "已過濾",
|
||||
"latency": "延遲"
|
||||
},
|
||||
"qbittorrent": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下行速率",
|
||||
"upload": "上行速率",
|
||||
"leech": "未完成下載",
|
||||
"seed": "已完成下載"
|
||||
},
|
||||
"mastodon": {
|
||||
"user_count": "Users",
|
||||
"status_count": "Posts",
|
||||
"domain_count": "Domains"
|
||||
"user_count": "使用者",
|
||||
"status_count": "文章",
|
||||
"domain_count": "網域"
|
||||
},
|
||||
"strelaysrv": {
|
||||
"numActiveSessions": "Sessions",
|
||||
"numConnections": "Connections",
|
||||
"dataRelayed": "Relayed",
|
||||
"transferRate": "Rate"
|
||||
"numActiveSessions": "工作階段",
|
||||
"numConnections": "連線",
|
||||
"dataRelayed": "中繼",
|
||||
"transferRate": "速率"
|
||||
},
|
||||
"authentik": {
|
||||
"users": "Users",
|
||||
"loginsLast24H": "Logins (24h)",
|
||||
"failedLoginsLast24H": "Failed Logins (24h)"
|
||||
"users": "使用者",
|
||||
"loginsLast24H": "登錄(24h)",
|
||||
"failedLoginsLast24H": "登錄失敗(24h)"
|
||||
},
|
||||
"proxmox": {
|
||||
"mem": "MEM",
|
||||
"mem": "記憶體",
|
||||
"cpu": "CPU",
|
||||
"lxc": "LXC",
|
||||
"vms": "VMs"
|
||||
},
|
||||
"unifi": {
|
||||
"users": "Users",
|
||||
"uptime": "System Uptime",
|
||||
"days": "Days",
|
||||
"users": "使用者",
|
||||
"uptime": "系統運行時間",
|
||||
"days": "天",
|
||||
"wan": "WAN",
|
||||
"lan_users": "LAN Users",
|
||||
"wlan_users": "WLAN Users",
|
||||
"lan_users": "LAN使用者",
|
||||
"wlan_users": "WLAN使用者",
|
||||
"up": "UP",
|
||||
"down": "DOWN",
|
||||
"wait": "Please wait",
|
||||
"wait": "請稍後",
|
||||
"lan": "LAN",
|
||||
"wlan": "WLAN",
|
||||
"devices": "Devices",
|
||||
"lan_devices": "LAN Devices",
|
||||
"wlan_devices": "WLAN Devices"
|
||||
"devices": "設備",
|
||||
"lan_devices": "LAN設備",
|
||||
"wlan_devices": "WLAN設備"
|
||||
},
|
||||
"plex": {
|
||||
"streams": "Active Streams",
|
||||
"movies": "Movies",
|
||||
"tv": "TV Shows"
|
||||
"streams": "正在播放",
|
||||
"movies": "電影",
|
||||
"tv": "影集"
|
||||
},
|
||||
"glances": {
|
||||
"cpu": "CPU",
|
||||
"mem": "MEM",
|
||||
"wait": "Please wait"
|
||||
"mem": "記憶體",
|
||||
"wait": "請稍後"
|
||||
},
|
||||
"changedetectionio": {
|
||||
"totalObserved": "Total Observed",
|
||||
"diffsDetected": "Diffs Detected"
|
||||
"totalObserved": "總監測數",
|
||||
"diffsDetected": "偵測到的變更"
|
||||
},
|
||||
"wmo": {
|
||||
"0-day": "Sunny",
|
||||
"0-night": "Clear",
|
||||
"71-day": "Light Snow",
|
||||
"71-night": "Light Snow",
|
||||
"1-day": "Mainly Sunny",
|
||||
"1-night": "Mainly Clear",
|
||||
"2-day": "Partly Cloudy",
|
||||
"2-night": "Partly Cloudy",
|
||||
"3-day": "Cloudy",
|
||||
"3-night": "Cloudy",
|
||||
"45-day": "Foggy",
|
||||
"45-night": "Foggy",
|
||||
"48-day": "Foggy",
|
||||
"48-night": "Foggy",
|
||||
"51-day": "Light Drizzle",
|
||||
"51-night": "Light Drizzle",
|
||||
"53-day": "Drizzle",
|
||||
"53-night": "Drizzle",
|
||||
"55-day": "Heavy Drizzle",
|
||||
"55-night": "Heavy Drizzle",
|
||||
"56-day": "Light Freezing Drizzle",
|
||||
"56-night": "Light Freezing Drizzle",
|
||||
"57-day": "Freezing Drizzle",
|
||||
"57-night": "Freezing Drizzle",
|
||||
"61-day": "Light Rain",
|
||||
"61-night": "Light Rain",
|
||||
"63-day": "Rain",
|
||||
"63-night": "Rain",
|
||||
"65-day": "Heavy Rain",
|
||||
"65-night": "Heavy Rain",
|
||||
"66-day": "Freezing Rain",
|
||||
"66-night": "Freezing Rain",
|
||||
"67-day": "Freezing Rain",
|
||||
"67-night": "Freezing Rain",
|
||||
"73-day": "Snow",
|
||||
"73-night": "Snow",
|
||||
"75-day": "Heavy Snow",
|
||||
"75-night": "Heavy Snow",
|
||||
"77-day": "Snow Grains",
|
||||
"77-night": "Snow Grains",
|
||||
"80-day": "Light Showers",
|
||||
"80-night": "Light Showers",
|
||||
"81-day": "Showers",
|
||||
"81-night": "Showers",
|
||||
"82-day": "Heavy Showers",
|
||||
"82-night": "Heavy Showers",
|
||||
"85-day": "Snow Showers",
|
||||
"85-night": "Snow Showers",
|
||||
"86-day": "Snow Showers",
|
||||
"86-night": "Snow Showers",
|
||||
"95-day": "Thunderstorm",
|
||||
"95-night": "Thunderstorm",
|
||||
"96-day": "Thunderstorm With Hail",
|
||||
"96-night": "Thunderstorm With Hail",
|
||||
"99-day": "Thunderstorm With Hail",
|
||||
"99-night": "Thunderstorm With Hail"
|
||||
"0-day": "晴",
|
||||
"0-night": "晴朗",
|
||||
"71-day": "小雪",
|
||||
"71-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": "凍雨",
|
||||
"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": "雷雨伴隨冰雹"
|
||||
},
|
||||
"quicklaunch": {
|
||||
"bookmark": "Bookmark",
|
||||
"service": "Service"
|
||||
"bookmark": "書籤",
|
||||
"service": "服務",
|
||||
"search": "Search",
|
||||
"custom": "Custom"
|
||||
},
|
||||
"homebridge": {
|
||||
"available_update": "System",
|
||||
"updates": "Updates",
|
||||
"update_available": "Update Available",
|
||||
"up_to_date": "Up to Date",
|
||||
"available_update": "系統",
|
||||
"updates": "更新",
|
||||
"update_available": "有可用的更新",
|
||||
"up_to_date": "已更新至最新",
|
||||
"child_bridges": "Child Bridges",
|
||||
"child_bridges_status": "{{ok}}/{{total}}"
|
||||
},
|
||||
"autobrr": {
|
||||
"approvedPushes": "Approved",
|
||||
"rejectedPushes": "Rejected",
|
||||
"filters": "Filters",
|
||||
"indexers": "Indexers"
|
||||
"approvedPushes": "接受",
|
||||
"rejectedPushes": "拒絕",
|
||||
"filters": "篩選器",
|
||||
"indexers": "索引器"
|
||||
},
|
||||
"watchtower": {
|
||||
"containers_scanned": "Scanned",
|
||||
"containers_updated": "Updated",
|
||||
"containers_failed": "Failed"
|
||||
"containers_scanned": "已掃描",
|
||||
"containers_updated": "已更新",
|
||||
"containers_failed": "失敗"
|
||||
},
|
||||
"tubearchivist": {
|
||||
"downloads": "Queue",
|
||||
"videos": "Videos",
|
||||
"channels": "Channels",
|
||||
"playlists": "Playlists"
|
||||
"downloads": "佇列",
|
||||
"videos": "影片",
|
||||
"channels": "頻道",
|
||||
"playlists": "播放清單"
|
||||
},
|
||||
"truenas": {
|
||||
"load": "System Load",
|
||||
"uptime": "Uptime",
|
||||
"alerts": "Alerts",
|
||||
"load": "系統負載",
|
||||
"uptime": "運行時間",
|
||||
"alerts": "警示",
|
||||
"time": "{{value, number(style: unit; unitDisplay: long;)}}"
|
||||
},
|
||||
"navidrome": {
|
||||
"nothing_streaming": "No Active Streams",
|
||||
"please_wait": "Please Wait"
|
||||
"nothing_streaming": "無播放活動",
|
||||
"please_wait": "請稍後"
|
||||
},
|
||||
"pyload": {
|
||||
"speed": "Speed",
|
||||
"active": "Active",
|
||||
"queue": "Queue",
|
||||
"total": "Total"
|
||||
"speed": "速度",
|
||||
"active": "運行中",
|
||||
"queue": "佇列",
|
||||
"total": "全部"
|
||||
},
|
||||
"gluetun": {
|
||||
"public_ip": "Public IP",
|
||||
"region": "Region",
|
||||
"country": "Country"
|
||||
"public_ip": "公用IP",
|
||||
"region": "地區",
|
||||
"country": "國家"
|
||||
},
|
||||
"hdhomerun": {
|
||||
"channels": "Channels",
|
||||
"hd": "HD"
|
||||
"channels": "頻道",
|
||||
"hd": "高畫質"
|
||||
},
|
||||
"ping": {
|
||||
"error": "Error",
|
||||
"error": "錯誤",
|
||||
"ping": "Ping"
|
||||
},
|
||||
"scrutiny": {
|
||||
"passed": "Passed",
|
||||
"failed": "Failed",
|
||||
"unknown": "Unknown"
|
||||
"passed": "通過",
|
||||
"failed": "失敗",
|
||||
"unknown": "未知的"
|
||||
},
|
||||
"paperlessngx": {
|
||||
"inbox": "Inbox",
|
||||
"total": "Total"
|
||||
"inbox": "收件箱",
|
||||
"total": "全部"
|
||||
},
|
||||
"deluge": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下行速率",
|
||||
"upload": "上行速率",
|
||||
"leech": "未完成下載",
|
||||
"seed": "已完成下載"
|
||||
},
|
||||
"flood": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下行速率",
|
||||
"upload": "上行速率",
|
||||
"leech": "未完成下載",
|
||||
"seed": "已完成下載"
|
||||
},
|
||||
"tdarr": {
|
||||
"queue": "Queue",
|
||||
"processed": "Processed",
|
||||
"errored": "Errored",
|
||||
"saved": "Saved"
|
||||
"queue": "佇列",
|
||||
"processed": "已處理",
|
||||
"errored": "發生錯誤",
|
||||
"saved": "已儲存"
|
||||
},
|
||||
"miniflux": {
|
||||
"read": "Read",
|
||||
"unread": "Unread"
|
||||
"read": "已讀",
|
||||
"unread": "未讀"
|
||||
},
|
||||
"nextdns": {
|
||||
"wait": "Please Wait",
|
||||
"no_devices": "No Device Data Received"
|
||||
"wait": "請稍後",
|
||||
"no_devices": "未收到裝置資料"
|
||||
},
|
||||
"common": {
|
||||
"bibyterate": "{{value, rate(bits: false; binary: true)}}",
|
||||
"bibitrate": "{{value, rate(bits: true; binary: true)}}"
|
||||
},
|
||||
"omada": {
|
||||
"connectedAp": "Connected APs",
|
||||
"activeUser": "Active devices",
|
||||
"alerts": "Alerts",
|
||||
"connectedGateway": "Connected gateways",
|
||||
"connectedSwitches": "Connected switches"
|
||||
"connectedAp": "已連接的存取點",
|
||||
"activeUser": "在線裝置",
|
||||
"alerts": "警示",
|
||||
"connectedGateway": "已連接的閘道",
|
||||
"connectedSwitches": "已連接的交換器"
|
||||
},
|
||||
"downloadstation": {
|
||||
"download": "Download",
|
||||
"upload": "Upload",
|
||||
"leech": "Leech",
|
||||
"seed": "Seed"
|
||||
"download": "下行速率",
|
||||
"upload": "上行速率",
|
||||
"leech": "未完成下載",
|
||||
"seed": "已完成下載"
|
||||
},
|
||||
"mikrotik": {
|
||||
"cpuLoad": "CPU Load",
|
||||
"memoryUsed": "Memory Used",
|
||||
"uptime": "Uptime",
|
||||
"numberOfLeases": "Leases"
|
||||
"cpuLoad": "CPU負載",
|
||||
"memoryUsed": "已使用的記憶體",
|
||||
"uptime": "運行時間",
|
||||
"numberOfLeases": "租約"
|
||||
},
|
||||
"xteve": {
|
||||
"streams_all": "All Streams",
|
||||
"streams_active": "Active Streams",
|
||||
"streams_xepg": "XEPG Channels"
|
||||
"streams_all": "所有播放活動",
|
||||
"streams_active": "正在播放",
|
||||
"streams_xepg": "XEPG頻道"
|
||||
},
|
||||
"opnsense": {
|
||||
"cpu": "CPU Load",
|
||||
"cpu": "CPU負載",
|
||||
"memory": "Active Memory",
|
||||
"wanUpload": "WAN Upload",
|
||||
"wanDownload": "WAN Download"
|
||||
"wanUpload": "WAN上傳",
|
||||
"wanDownload": "WAN下載"
|
||||
},
|
||||
"moonraker": {
|
||||
"printer_state": "列印機狀態",
|
||||
"print_status": "列印狀態",
|
||||
"print_progress": "進度",
|
||||
"layers": "層"
|
||||
},
|
||||
"medusa": {
|
||||
"wanted": "關注中",
|
||||
"queued": "已加入佇列",
|
||||
"series": "影集"
|
||||
},
|
||||
"octoprint": {
|
||||
"printer_state": "狀態",
|
||||
"temp_tool": "噴頭溫度",
|
||||
"temp_bed": "平台溫度",
|
||||
"job_completion": "完成度"
|
||||
},
|
||||
"cloudflared": {
|
||||
"origin_ip": "Origin IP",
|
||||
"status": "Status"
|
||||
},
|
||||
"proxmoxbackupserver": {
|
||||
"datastore_usage": "Datastore",
|
||||
"failed_tasks_24h": "Failed Tasks 24h",
|
||||
"cpu_usage": "CPU",
|
||||
"memory_usage": "Memory"
|
||||
},
|
||||
"immich": {
|
||||
"users": "Users",
|
||||
"photos": "Photos",
|
||||
"videos": "Videos",
|
||||
"storage": "Storage"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function Item({ bookmark }) {
|
||||
<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 w-5 h-5">
|
||||
<ResolvedIcon icon={bookmark.icon} />
|
||||
<ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
|
||||
</div>
|
||||
}
|
||||
{!bookmark.icon && bookmark.abbr}
|
||||
|
||||
@@ -6,7 +6,7 @@ import ResolvedIcon from "./resolvedicon";
|
||||
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
|
||||
export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close, searchDescriptions}) {
|
||||
export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close, searchDescriptions, searchProvider}) {
|
||||
const { t } = useTranslation();
|
||||
const { settings } = useContext(SettingsContext);
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
|
||||
function handleSearchKeyDown(event) {
|
||||
if (!isOpen) return;
|
||||
|
||||
|
||||
if (event.key === "Escape") {
|
||||
closeAndReset();
|
||||
event.preventDefault();
|
||||
@@ -50,6 +50,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleItemHover(event) {
|
||||
setCurrentItemIndex(parseInt(event.target?.dataset?.index, 10));
|
||||
}
|
||||
@@ -75,6 +76,15 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
if (searchDescriptions) {
|
||||
newResults = newResults.sort((a, b) => b.priority - a.priority);
|
||||
}
|
||||
if (searchProvider) {
|
||||
newResults.push(
|
||||
{
|
||||
href: searchProvider.url + encodeURIComponent(searchString),
|
||||
name: `${searchProvider.name ?? t("quicklaunch.custom")} ${t("quicklaunch.search")} `,
|
||||
type: 'search',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
setResults(newResults);
|
||||
|
||||
@@ -82,7 +92,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
setCurrentItemIndex(0);
|
||||
}
|
||||
}
|
||||
}, [searchString, servicesAndBookmarks, searchDescriptions]);
|
||||
}, [searchString, servicesAndBookmarks, searchDescriptions, searchProvider, t]);
|
||||
|
||||
|
||||
const [hidden, setHidden] = useState(true);
|
||||
@@ -90,7 +100,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
function handleBackdropClick(event) {
|
||||
if (event.target?.tagName === "DIV") closeAndReset();
|
||||
}
|
||||
|
||||
|
||||
if (isOpen) {
|
||||
searchField.current.focus();
|
||||
document.body.addEventListener('click', handleBackdropClick);
|
||||
@@ -135,20 +145,20 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
||||
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
|
||||
)} onClick={handleItemClick}>
|
||||
<div className="flex flex-row items-center mr-4 pointer-events-none">
|
||||
<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.abbr && r.abbr}
|
||||
</div>
|
||||
</div>}
|
||||
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
|
||||
<span className="mr-4">{r.name}</span>
|
||||
{r.description &&
|
||||
{r.description &&
|
||||
<span className="text-xs text-theme-600 text-light">
|
||||
{searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-theme-600 font-bold pointer-events-none">{r.type === 'service' ? t("quicklaunch.service") : t("quicklaunch.bookmark")}</div>
|
||||
<div className="text-xs text-theme-600 font-bold pointer-events-none">{t(`quicklaunch.${r.type ? r.type.toLowerCase() : 'bookmark'}`)}</div>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Image from "next/future/image";
|
||||
|
||||
export default function ResolvedIcon({ icon, width = 32, height = 32 }) {
|
||||
export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "logo" }) {
|
||||
// direct or relative URLs
|
||||
if (icon.startsWith("http") || icon.startsWith("/")) {
|
||||
return <Image src={`${icon}`} width={width} height={height} alt="logo" />;
|
||||
return <Image src={`${icon}`} width={width} height={height} alt={alt} />;
|
||||
}
|
||||
|
||||
// mdi- prefixed, material design icons
|
||||
@@ -31,7 +31,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32 }) {
|
||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
||||
width={width}
|
||||
height={height}
|
||||
alt="logo"
|
||||
alt={alt}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import { useContext, useState } from "react";
|
||||
import Status from "./status";
|
||||
import Widget from "./widget";
|
||||
import Ping from "./ping";
|
||||
import KubernetesStatus from "./kubernetes-status";
|
||||
|
||||
import Docker from "widgets/docker/component";
|
||||
import Kubernetes from "widgets/kubernetes/component";
|
||||
import { SettingsContext } from "utils/contexts/settings";
|
||||
import ResolvedIcon from "components/resolvedicon";
|
||||
|
||||
@@ -89,6 +91,16 @@ export default function Item({ service }) {
|
||||
<span className="sr-only">View container stats</span>
|
||||
</button>
|
||||
)}
|
||||
{service.app && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => (statsOpen ? closeStats() : setStatsOpen(true))}
|
||||
className="flex-shrink-0 flex items-center justify-center cursor-pointer"
|
||||
>
|
||||
<KubernetesStatus service={service} />
|
||||
<span className="sr-only">View container stats</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -102,6 +114,16 @@ export default function Item({ service }) {
|
||||
{statsOpen && <Docker service={{ widget: { container: service.container, server: service.server } }} />}
|
||||
</div>
|
||||
)}
|
||||
{service.app && (
|
||||
<div
|
||||
className={classNames(
|
||||
statsOpen && !statsClosing ? "max-h-[55px] opacity-100" : " max-h-[0] opacity-0",
|
||||
"w-full overflow-hidden transition-all duration-300 ease-in-out"
|
||||
)}
|
||||
>
|
||||
{statsOpen && <Kubernetes service={{ widget: { namespace: service.namespace, app: service.app, podSelector: service.podSelector } }} />}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{service.widget && <Widget service={service} />}
|
||||
</div>
|
||||
|
||||
35
src/components/services/kubernetes-status.jsx
Normal file
35
src/components/services/kubernetes-status.jsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import useSWR from "swr";
|
||||
import { t } from "i18next";
|
||||
|
||||
export default function KubernetesStatus({ service }) {
|
||||
const podSelectorString = service.podSelector !== undefined ? `podSelector=${service.podSelector}` : "";
|
||||
const { data, error } = useSWR(`/api/kubernetes/status/${service.namespace}/${service.app}?${podSelectorString}`);
|
||||
|
||||
if (error) {
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}>
|
||||
<div className="text-[8px] font-bold text-rose-500/80 uppercase">{t("docker.error")}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
if (data && data.status === "running") {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health ?? data.status}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (data && (data.status === "not found" || data.status === "down" || data.status === "partial")) {
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.status}>
|
||||
<div className="text-[8px] font-bold text-orange-400/50 dark:text-orange-400/80 uppercase">{data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden">
|
||||
<div className="text-[8px] font-bold text-black/20 dark:text-white/40 uppercase">{t("docker.unknown")}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -30,8 +30,8 @@ export default function Status({ service }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health ?? data.status}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health ?? data.status}</div>
|
||||
<div className="w-auto px-1.5 py-0.5 text-center bg-theme-500/10 dark:bg-theme-900/50 rounded-b-[3px] overflow-hidden" title={data.health || data.status}>
|
||||
<div className="text-[8px] font-bold text-emerald-500/80 uppercase">{data.health || data.status}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
74
src/components/widgets/kubernetes/kubernetes.jsx
Normal file
74
src/components/widgets/kubernetes/kubernetes.jsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import useSWR from "swr";
|
||||
import { BiError } from "react-icons/bi";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Node from "./node";
|
||||
|
||||
export default function Widget({ options }) {
|
||||
const { cluster, nodes } = options;
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const defaultData = {
|
||||
cpu: {
|
||||
load: 0,
|
||||
total: 0,
|
||||
percent: 0
|
||||
},
|
||||
memory: {
|
||||
used: 0,
|
||||
total: 0,
|
||||
free: 0,
|
||||
precent: 0
|
||||
}
|
||||
};
|
||||
|
||||
const { data, error } = useSWR(
|
||||
`/api/widgets/kubernetes?${new URLSearchParams({ lang: i18n.language }).toString()}`, {
|
||||
refreshInterval: 1500
|
||||
}
|
||||
);
|
||||
|
||||
if (error || data?.error) {
|
||||
return (
|
||||
<div className="flex flex-col justify-center first:ml-0 ml-4">
|
||||
<div className="flex flex-row items-center justify-end">
|
||||
<div className="flex flex-row items-center">
|
||||
<BiError className="w-8 h-8 text-theme-800 dark:text-theme-200" />
|
||||
<div className="flex flex-col ml-3 text-left">
|
||||
<span className="text-theme-800 dark:text-theme-200 text-sm">{t("widget.api_error")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap">
|
||||
<div className="flex flex-row self-center flex-wrap justify-between">
|
||||
{cluster.show &&
|
||||
<Node type="cluster" key="cluster" options={options.cluster} data={defaultData} />
|
||||
}
|
||||
{nodes.show &&
|
||||
<Node type="node" key="nodes" options={options.nodes} data={defaultData} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap">
|
||||
<div className="flex flex-row self-center flex-wrap justify-between">
|
||||
{cluster.show &&
|
||||
<Node key="cluster" type="cluster" options={options.cluster} data={data.cluster} />
|
||||
}
|
||||
{nodes.show && data.nodes &&
|
||||
data.nodes.map((node) =>
|
||||
<Node key={node.name} type="node" options={options.nodes} data={node} />)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
60
src/components/widgets/kubernetes/node.jsx
Normal file
60
src/components/widgets/kubernetes/node.jsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { FaMemory } from "react-icons/fa";
|
||||
import { FiAlertTriangle, FiCpu, FiServer } from "react-icons/fi";
|
||||
import { SiKubernetes } from "react-icons/si";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import UsageBar from "./usage-bar";
|
||||
|
||||
|
||||
export default function Node({ type, options, data }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
function icon() {
|
||||
if (type === "cluster") {
|
||||
return <SiKubernetes className="text-theme-800 dark:text-theme-200 w-5 h-5" />;
|
||||
}
|
||||
if (data.ready) {
|
||||
return <FiServer className="text-theme-800 dark:text-theme-200 w-5 h-5" />;
|
||||
}
|
||||
return <FiAlertTriangle className="text-theme-800 dark:text-theme-200 w-5 h-5" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap ml-4">
|
||||
<div className="flex flex-row self-center flex-wrap justify-between">
|
||||
<div className="flex-none flex flex-row items-center mr-3 py-1.5">
|
||||
{icon()}
|
||||
<div className="flex flex-col ml-3 text-left min-w-[85px]">
|
||||
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
||||
<div className="pl-0.5">
|
||||
{t("common.number", {
|
||||
value: data.cpu.percent,
|
||||
style: "unit",
|
||||
unit: "percent",
|
||||
maximumFractionDigits: 0
|
||||
})}
|
||||
</div>
|
||||
<FiCpu className="text-theme-800 dark:text-theme-200 w-3 h-3" />
|
||||
</div>
|
||||
<UsageBar percent={data.cpu.percent} />
|
||||
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
||||
<div className="pl-0.5">
|
||||
{t("common.bytes", {
|
||||
value: data.memory.free,
|
||||
maximumFractionDigits: 0,
|
||||
binary: true
|
||||
})}
|
||||
</div>
|
||||
<FaMemory className="text-theme-800 dark:text-theme-200 w-3 h-3" />
|
||||
</div>
|
||||
<UsageBar percent={data.memory.percent} />
|
||||
{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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
src/components/widgets/kubernetes/usage-bar.jsx
Normal file
12
src/components/widgets/kubernetes/usage-bar.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
export default function UsageBar({ percent }) {
|
||||
return (
|
||||
<div className="mt-0.5 w-full bg-theme-800/30 rounded-full h-1 dark:bg-theme-200/20">
|
||||
<div
|
||||
className="bg-theme-800/70 h-1 rounded-full dark:bg-theme-200/50 transition-all duration-1000"
|
||||
style={{
|
||||
width: `${percent}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
57
src/components/widgets/longhorn/longhorn.jsx
Normal file
57
src/components/widgets/longhorn/longhorn.jsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import useSWR from "swr";
|
||||
import { BiError } from "react-icons/bi";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Node from "./node";
|
||||
|
||||
export default function Longhorn({ options }) {
|
||||
const { expanded, total, labels, include, nodes } = options;
|
||||
const { t } = useTranslation();
|
||||
const { data, error } = useSWR(`/api/widgets/longhorn`, {
|
||||
refreshInterval: 1500
|
||||
});
|
||||
|
||||
if (error || data?.error) {
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap">
|
||||
<BiError className="text-theme-800 dark:text-theme-200 w-5 h-5" />
|
||||
<div className="flex flex-col ml-3 text-left">
|
||||
<span className="text-theme-800 dark:text-theme-200 text-xs">{t("widget.api_error")}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap">
|
||||
<div className="flex flex-row self-center flex-wrap justify-between" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col max-w:full sm:basis-auto self-center grow-0 flex-wrap">
|
||||
<div className="flex flex-row self-center flex-wrap justify-between">
|
||||
{data.nodes
|
||||
.filter((node) => {
|
||||
if (node.id === 'total' && total) {
|
||||
return true;
|
||||
}
|
||||
if (!nodes) {
|
||||
return false;
|
||||
}
|
||||
if (include && !include.includes(node.id)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((node) =>
|
||||
<div key={node.id}>
|
||||
<Node data={{ node }} expanded={expanded} labels={labels} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
32
src/components/widgets/longhorn/node.jsx
Normal file
32
src/components/widgets/longhorn/node.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { FiHardDrive } from "react-icons/fi";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import UsageBar from "../resources/usage-bar";
|
||||
|
||||
export default function Node({ data, expanded, labels }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex-none flex flex-row items-center mr-3 py-1.5">
|
||||
<FiHardDrive className="text-theme-800 dark:text-theme-200 w-5 h-5" />
|
||||
<div className="flex flex-col ml-3 text-left min-w-[85px]">
|
||||
<span className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
||||
<div className="pl-0.5">{t("common.bytes", { value: data.node.available })}</div>
|
||||
<div className="pr-1">{t("resources.free")}</div>
|
||||
</span>
|
||||
{expanded && (
|
||||
<span className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
|
||||
<div className="pl-0.5">{t("common.bytes", { value: data.node.maximum })}</div>
|
||||
<div className="pr-1">{t("resources.total")}</div>
|
||||
</span>
|
||||
)}
|
||||
<UsageBar percent={Math.round(((data.node.maximum - data.node.available) / data.node.maximum) * 100)} />
|
||||
</div>
|
||||
</div>
|
||||
{labels && (
|
||||
<div className="ml-6 pt-1 text-center text-theme-800 dark:text-theme-200 text-xs">{data.node.id}</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect, Fragment } from "react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { FiSearch } from "react-icons/fi";
|
||||
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu } from "react-icons/si";
|
||||
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
import classNames from "classnames";
|
||||
|
||||
const providers = {
|
||||
export const searchProviders = {
|
||||
google: {
|
||||
name: "Google",
|
||||
url: "https://www.google.com/search?q=",
|
||||
@@ -24,6 +26,11 @@ const providers = {
|
||||
url: "https://www.baidu.com/s?wd=",
|
||||
icon: SiBaidu,
|
||||
},
|
||||
brave: {
|
||||
name: "Brave",
|
||||
url: "https://search.brave.com/search?q=",
|
||||
icon: SiBrave,
|
||||
},
|
||||
custom: {
|
||||
name: "Custom",
|
||||
url: false,
|
||||
@@ -31,21 +38,55 @@ const providers = {
|
||||
},
|
||||
};
|
||||
|
||||
function getAvailableProviderIds(options) {
|
||||
if (options.provider && Array.isArray(options.provider)) {
|
||||
return Object.keys(searchProviders).filter((value) => options.provider.includes(value));
|
||||
}
|
||||
if (options.provider && searchProviders[options.provider]) {
|
||||
return [options.provider];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const localStorageKey = "search-name";
|
||||
|
||||
export function getStoredProvider() {
|
||||
if (typeof window !== 'undefined') {
|
||||
const storedName = localStorage.getItem(localStorageKey);
|
||||
if (storedName) {
|
||||
return Object.values(searchProviders).find((el) => el.name === storedName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function Search({ options }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const provider = providers[options.provider];
|
||||
const [query, setQuery] = useState("");
|
||||
const availableProviderIds = getAvailableProviderIds(options);
|
||||
|
||||
if (!provider) {
|
||||
const [query, setQuery] = useState("");
|
||||
const [selectedProvider, setSelectedProvider] = useState(searchProviders[availableProviderIds[0] ?? searchProviders.google]);
|
||||
|
||||
useEffect(() => {
|
||||
const storedProvider = getStoredProvider();
|
||||
let storedProviderKey = null;
|
||||
storedProviderKey = Object.keys(searchProviders).find((pkey) => searchProviders[pkey] === storedProvider);
|
||||
if (storedProvider && availableProviderIds.includes(storedProviderKey)) {
|
||||
setSelectedProvider(storedProvider);
|
||||
}
|
||||
}, [availableProviderIds]);
|
||||
|
||||
if (!availableProviderIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function handleSubmit(event) {
|
||||
const q = encodeURIComponent(query);
|
||||
|
||||
if (provider.url) {
|
||||
window.open(`${provider.url}${q}`, options.target || "_blank");
|
||||
const url = { selectedProvider };
|
||||
if (url) {
|
||||
window.open(`${url}${q}`, options.target || "_blank");
|
||||
} else {
|
||||
window.open(`${options.url}${q}`, options.target || "_blank");
|
||||
}
|
||||
@@ -55,6 +96,11 @@ export default function Search({ options }) {
|
||||
setQuery("");
|
||||
}
|
||||
|
||||
const onChangeProvider = (provider) => {
|
||||
setSelectedProvider(provider);
|
||||
localStorage.setItem(localStorageKey, provider.name);
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="flex-col relative h-8 my-4 min-w-fit grow first:ml-0 ml-4" onSubmit={handleSubmit}>
|
||||
<div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" />
|
||||
@@ -77,17 +123,55 @@ export default function Search({ options }) {
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus={options.focus}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="
|
||||
<Listbox as="div" value={selectedProvider} onChange={onChangeProvider} className="relative text-left" disabled={availableProviderIds?.length === 1}>
|
||||
<div>
|
||||
<Listbox.Button
|
||||
className="
|
||||
absolute right-0.5 bottom-0.5 rounded-r-md px-4 py-2 border-1
|
||||
text-white font-medium text-sm
|
||||
bg-theme-600/40 dark:bg-white/10
|
||||
focus:ring-theme-500 dark:focus:ring-white/50"
|
||||
>
|
||||
<provider.icon className="text-white w-3 h-3" />
|
||||
<span className="sr-only">{t("search.search")}</span>
|
||||
</button>
|
||||
>
|
||||
<selectedProvider.icon className="text-white w-3 h-3" />
|
||||
<span className="sr-only">{t("search.search")}</span>
|
||||
</Listbox.Button>
|
||||
</div>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-100"
|
||||
enterFrom="transform opacity-0 scale-95"
|
||||
enterTo="transform opacity-100 scale-100"
|
||||
leave="transition ease-in duration-75"
|
||||
leaveFrom="transform opacity-100 scale-100"
|
||||
leaveTo="transform opacity-0 scale-95"
|
||||
>
|
||||
<Listbox.Options
|
||||
className="absolute right-0 z-10 mt-1 origin-top-right rounded-md
|
||||
bg-theme-100 dark:bg-theme-600 shadow-lg
|
||||
ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
{availableProviderIds.map((providerId) => {
|
||||
const p = searchProviders[providerId];
|
||||
return (
|
||||
<Listbox.Option key={providerId} value={p} as={Fragment}>
|
||||
{({ active }) => (
|
||||
<li
|
||||
className={classNames(
|
||||
"rounded-md cursor-pointer",
|
||||
active ? "bg-theme-600/10 dark:bg-white/10 dark:text-gray-900" : "dark:text-gray-100"
|
||||
)}
|
||||
>
|
||||
<p.icon className="h-4 w-4 mx-4 my-2" />
|
||||
</li>
|
||||
)}
|
||||
</Listbox.Option>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Listbox.Options>
|
||||
</Transition>
|
||||
</Listbox>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ const widgetMappings = {
|
||||
unifi_console: dynamic(() => import("components/widgets/unifi_console/unifi_console")),
|
||||
glances: dynamic(() => import("components/widgets/glances/glances")),
|
||||
openmeteo: dynamic(() => import("components/widgets/openmeteo/openmeteo")),
|
||||
longhorn: dynamic(() => import("components/widgets/longhorn/longhorn")),
|
||||
kubernetes: dynamic(() => import("components/widgets/kubernetes/kubernetes")),
|
||||
};
|
||||
|
||||
export default function Widget({ widget }) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import Head from "next/head";
|
||||
import "styles/globals.css";
|
||||
import "styles/theme.css";
|
||||
import "styles/manrope.css";
|
||||
import "styles/custom.css";
|
||||
import nextI18nextConfig from "../../next-i18next.config";
|
||||
|
||||
import { ColorProvider } from "utils/contexts/color";
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import Docker from "dockerode";
|
||||
|
||||
import getDockerArguments from "utils/config/docker";
|
||||
import createLogger from "utils/logger";
|
||||
|
||||
const logger = createLogger("dockerStatsService");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const { service } = req.query;
|
||||
const [containerName, containerServer] = service;
|
||||
|
||||
if (!containerName && !containerServer) {
|
||||
res.status(400).send({
|
||||
return res.status(400).send({
|
||||
error: "docker query parameters are required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -23,10 +25,9 @@ export default async function handler(req, res) {
|
||||
// bad docker connections can result in a <Buffer ...> object?
|
||||
// in any case, this ensures the result is the expected array
|
||||
if (!Array.isArray(containers)) {
|
||||
res.status(500).send({
|
||||
return res.status(500).send({
|
||||
error: "query failed",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const containerNames = containers.map((container) => container.Names[0].replace(/^\//, ""));
|
||||
@@ -36,10 +37,9 @@ export default async function handler(req, res) {
|
||||
const container = docker.getContainer(containerName);
|
||||
const stats = await container.stats({ stream: false });
|
||||
|
||||
res.status(200).json({
|
||||
return res.status(200).json({
|
||||
stats,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Try with a service deployed in Docker Swarm, if enabled
|
||||
@@ -61,19 +61,19 @@ export default async function handler(req, res) {
|
||||
const container = docker.getContainer(taskContainerId);
|
||||
const stats = await container.stats({ stream: false });
|
||||
|
||||
res.status(200).json({
|
||||
return res.status(200).json({
|
||||
stats,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).send({
|
||||
return res.status(200).send({
|
||||
error: "not found",
|
||||
});
|
||||
} catch {
|
||||
res.status(500).send({
|
||||
error: {message: "Unknown error"},
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
return res.status(500).send({
|
||||
error: {message: e?.message ?? "Unknown error"},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import Docker from "dockerode";
|
||||
|
||||
import getDockerArguments from "utils/config/docker";
|
||||
import createLogger from "utils/logger";
|
||||
|
||||
const logger = createLogger("dockerStatusService");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const { service } = req.query;
|
||||
@@ -68,9 +71,10 @@ export default async function handler(req, res) {
|
||||
return res.status(200).send({
|
||||
error: "not found",
|
||||
});
|
||||
} catch {
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
return res.status(500).send({
|
||||
error: "unknown error",
|
||||
error: {message: e?.message ?? "Unknown error"},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
110
src/pages/api/kubernetes/stats/[...service].js
Normal file
110
src/pages/api/kubernetes/stats/[...service].js
Normal file
@@ -0,0 +1,110 @@
|
||||
import { CoreV1Api, Metrics } from "@kubernetes/client-node";
|
||||
|
||||
import getKubeConfig from "../../../../utils/config/kubernetes";
|
||||
import { parseCpu, parseMemory } from "../../../../utils/kubernetes/kubernetes-utils";
|
||||
import createLogger from "../../../../utils/logger";
|
||||
|
||||
const logger = createLogger("kubernetesStatsService");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const APP_LABEL = "app.kubernetes.io/name";
|
||||
const { service, podSelector } = req.query;
|
||||
|
||||
const [namespace, appName] = service;
|
||||
if (!namespace && !appName) {
|
||||
res.status(400).send({
|
||||
error: "kubernetes query parameters are required"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`;
|
||||
|
||||
try {
|
||||
const kc = getKubeConfig();
|
||||
if (!kc) {
|
||||
res.status(500).send({
|
||||
error: "No kubernetes configuration"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const coreApi = kc.makeApiClient(CoreV1Api);
|
||||
const metricsApi = new Metrics(kc);
|
||||
const podsResponse = await coreApi.listNamespacedPod(namespace, null, null, null, null, labelSelector)
|
||||
.then((response) => response.body)
|
||||
.catch((err) => {
|
||||
logger.error("Error getting pods: %d %s %s", err.statusCode, err.body, err.response);
|
||||
return null;
|
||||
});
|
||||
if (!podsResponse) {
|
||||
res.status(500).send({
|
||||
error: "Error communicating with kubernetes"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const pods = podsResponse.items;
|
||||
|
||||
if (pods.length === 0) {
|
||||
res.status(404).send({
|
||||
error: "not found"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let cpuLimit = 0;
|
||||
let memLimit = 0;
|
||||
pods.forEach((pod) => {
|
||||
pod.spec.containers.forEach((container) => {
|
||||
if (container?.resources?.limits?.cpu) {
|
||||
cpuLimit += parseCpu(container?.resources?.limits?.cpu);
|
||||
}
|
||||
if (container?.resources?.limits?.memory) {
|
||||
memLimit += parseMemory(container?.resources?.limits?.memory);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const podStatsList = await Promise.all(pods.map(async (pod) => {
|
||||
let depMem = 0;
|
||||
let depCpu = 0;
|
||||
const podMetrics = await metricsApi.getPodMetrics(namespace, pod.metadata.name)
|
||||
.then((response) => response)
|
||||
.catch((err) => {
|
||||
// 404 generally means that the metrics have not been populated yet
|
||||
if (err.statusCode !== 404) {
|
||||
logger.error("Error getting pod metrics: %d %s %s", err.statusCode, err.body, err.response);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (podMetrics) {
|
||||
podMetrics.containers.forEach((container) => {
|
||||
depMem += parseMemory(container.usage.memory);
|
||||
depCpu += parseCpu(container.usage.cpu);
|
||||
});
|
||||
}
|
||||
return {
|
||||
mem: depMem,
|
||||
cpu: depCpu
|
||||
};
|
||||
}));
|
||||
const stats = {
|
||||
mem: 0,
|
||||
cpu: 0
|
||||
}
|
||||
podStatsList.forEach((podStat) => {
|
||||
stats.mem += podStat.mem;
|
||||
stats.cpu += podStat.cpu;
|
||||
});
|
||||
stats.cpuLimit = cpuLimit;
|
||||
stats.memLimit = memLimit;
|
||||
stats.cpuUsage = cpuLimit ? stats.cpu / cpuLimit : 0;
|
||||
stats.memUsage = memLimit ? stats.mem / memLimit : 0;
|
||||
res.status(200).json({
|
||||
stats
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
res.status(500).send({
|
||||
error: "unknown error"
|
||||
});
|
||||
}
|
||||
}
|
||||
66
src/pages/api/kubernetes/status/[...service].js
Normal file
66
src/pages/api/kubernetes/status/[...service].js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { CoreV1Api } from "@kubernetes/client-node";
|
||||
|
||||
import getKubeConfig from "../../../../utils/config/kubernetes";
|
||||
import createLogger from "../../../../utils/logger";
|
||||
|
||||
const logger = createLogger("kubernetesStatusService");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const APP_LABEL = "app.kubernetes.io/name";
|
||||
const { service, podSelector } = req.query;
|
||||
|
||||
const [namespace, appName] = service;
|
||||
if (!namespace && !appName) {
|
||||
res.status(400).send({
|
||||
error: "kubernetes query parameters are required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const labelSelector = podSelector !== undefined ? podSelector : `${APP_LABEL}=${appName}`;
|
||||
try {
|
||||
const kc = getKubeConfig();
|
||||
if (!kc) {
|
||||
res.status(500).send({
|
||||
error: "No kubernetes configuration"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const coreApi = kc.makeApiClient(CoreV1Api);
|
||||
const podsResponse = await coreApi.listNamespacedPod(namespace, null, null, null, null, labelSelector)
|
||||
.then((response) => response.body)
|
||||
.catch((err) => {
|
||||
logger.error("Error getting pods: %d %s %s", err.statusCode, err.body, err.response);
|
||||
return null;
|
||||
});
|
||||
if (!podsResponse) {
|
||||
res.status(500).send({
|
||||
error: "Error communicating with kubernetes"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const pods = podsResponse.items;
|
||||
|
||||
if (pods.length === 0) {
|
||||
res.status(404).send({
|
||||
error: "not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const someReady = pods.find(pod => pod.status.phase === "Running");
|
||||
const allReady = pods.every((pod) => pod.status.phase === "Running");
|
||||
let status = "down";
|
||||
if (allReady) {
|
||||
status = "running";
|
||||
} else if (someReady) {
|
||||
status = "partial";
|
||||
}
|
||||
res.status(200).json({
|
||||
status
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
res.status(500).send({
|
||||
error: "unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
92
src/pages/api/widgets/kubernetes.js
Normal file
92
src/pages/api/widgets/kubernetes.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import { CoreV1Api, Metrics } from "@kubernetes/client-node";
|
||||
|
||||
import getKubeConfig from "../../../utils/config/kubernetes";
|
||||
import { parseCpu, parseMemory } from "../../../utils/kubernetes/kubernetes-utils";
|
||||
import createLogger from "../../../utils/logger";
|
||||
|
||||
const logger = createLogger("kubernetes-widget");
|
||||
|
||||
export default async function handler(req, res) {
|
||||
try {
|
||||
const kc = getKubeConfig();
|
||||
if (!kc) {
|
||||
return res.status(500).send({
|
||||
error: "No kubernetes configuration"
|
||||
});
|
||||
}
|
||||
const coreApi = kc.makeApiClient(CoreV1Api);
|
||||
const metricsApi = new Metrics(kc);
|
||||
|
||||
const nodes = await coreApi.listNode()
|
||||
.then((response) => response.body)
|
||||
.catch((error) => {
|
||||
logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response);
|
||||
return null;
|
||||
});
|
||||
if (!nodes) {
|
||||
return res.status(500).send({
|
||||
error: "unknown error"
|
||||
});
|
||||
}
|
||||
let cpuTotal = 0;
|
||||
let cpuUsage = 0;
|
||||
let memTotal = 0;
|
||||
let memUsage = 0;
|
||||
|
||||
const nodeMap = {};
|
||||
nodes.items.forEach((node) => {
|
||||
const cpu = Number.parseInt(node.status.capacity.cpu, 10);
|
||||
const mem = parseMemory(node.status.capacity.memory);
|
||||
const ready = node.status.conditions.filter(condition => condition.type === "Ready" && condition.status === "True").length > 0;
|
||||
nodeMap[node.metadata.name] = {
|
||||
name: node.metadata.name,
|
||||
ready,
|
||||
cpu: {
|
||||
total: cpu
|
||||
},
|
||||
memory: {
|
||||
total: mem
|
||||
}
|
||||
};
|
||||
cpuTotal += cpu;
|
||||
memTotal += mem;
|
||||
});
|
||||
|
||||
const nodeMetrics = await metricsApi.getNodeMetrics();
|
||||
nodeMetrics.items.forEach((nodeMetric) => {
|
||||
const cpu = parseCpu(nodeMetric.usage.cpu);
|
||||
const mem = parseMemory(nodeMetric.usage.memory);
|
||||
cpuUsage += cpu;
|
||||
memUsage += mem;
|
||||
nodeMap[nodeMetric.metadata.name].cpu.load = cpu;
|
||||
nodeMap[nodeMetric.metadata.name].cpu.percent = (cpu / nodeMap[nodeMetric.metadata.name].cpu.total) * 100;
|
||||
nodeMap[nodeMetric.metadata.name].memory.used = mem;
|
||||
nodeMap[nodeMetric.metadata.name].memory.free = nodeMap[nodeMetric.metadata.name].memory.total - mem;
|
||||
nodeMap[nodeMetric.metadata.name].memory.percent = (mem / nodeMap[nodeMetric.metadata.name].memory.total) * 100;
|
||||
});
|
||||
|
||||
const cluster = {
|
||||
cpu: {
|
||||
load: cpuUsage,
|
||||
total: cpuTotal,
|
||||
percent: (cpuUsage / cpuTotal) * 100
|
||||
},
|
||||
memory: {
|
||||
used: memUsage,
|
||||
total: memTotal,
|
||||
free: (memTotal - memUsage),
|
||||
percent: (memUsage / memTotal) * 100
|
||||
}
|
||||
};
|
||||
|
||||
return res.status(200).json({
|
||||
cluster,
|
||||
nodes: Object.entries(nodeMap).map(([name, node]) => ({ name, ...node }))
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error("exception %s", e);
|
||||
return res.status(500).send({
|
||||
error: "unknown error"
|
||||
});
|
||||
}
|
||||
}
|
||||
84
src/pages/api/widgets/longhorn.js
Normal file
84
src/pages/api/widgets/longhorn.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import { httpProxy } from "../../../utils/proxy/http";
|
||||
import createLogger from "../../../utils/logger";
|
||||
import { getSettings } from "../../../utils/config/config";
|
||||
|
||||
const logger = createLogger("longhorn");
|
||||
|
||||
function parseLonghornData(data) {
|
||||
const json = JSON.parse(data);
|
||||
|
||||
if (!json) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodes = json.data.map((node) => {
|
||||
let available = 0;
|
||||
let maximum = 0;
|
||||
let reserved = 0;
|
||||
let scheduled = 0;
|
||||
if (node.disks) {
|
||||
Object.keys(node.disks).forEach((diskKey) => {
|
||||
const disk = node.disks[diskKey];
|
||||
available += disk.storageAvailable;
|
||||
maximum += disk.storageMaximum;
|
||||
reserved += disk.storageReserved;
|
||||
scheduled += disk.storageScheduled;
|
||||
});
|
||||
}
|
||||
return {
|
||||
id: node.id,
|
||||
available,
|
||||
maximum,
|
||||
reserved,
|
||||
scheduled,
|
||||
};
|
||||
});
|
||||
const total = nodes.reduce((summary, node) => ({
|
||||
available: summary.available + node.available,
|
||||
maximum: summary.maximum + node.maximum,
|
||||
reserved: summary.reserved + node.reserved,
|
||||
scheduled: summary.scheduled + node.scheduled,
|
||||
}));
|
||||
total.id = "total";
|
||||
nodes.push(total);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
const settings = getSettings();
|
||||
const longhornSettings = settings?.providers?.longhorn;
|
||||
const {url, username, password} = longhornSettings;
|
||||
|
||||
if (!url) {
|
||||
const errorMessage = "Missing Longhorn URL";
|
||||
logger.error(errorMessage);
|
||||
return res.status(400).json({ error: errorMessage });
|
||||
}
|
||||
|
||||
const apiUrl = `${url}/v1/nodes`;
|
||||
const headers = {
|
||||
"Accept-Encoding": "application/json"
|
||||
};
|
||||
if (username && password) {
|
||||
headers.Authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`
|
||||
}
|
||||
const params = { method: "GET", headers };
|
||||
|
||||
const [status, contentType, data] = await httpProxy(apiUrl, params);
|
||||
|
||||
if (status === 401) {
|
||||
logger.error("Authorization failure getting data from Longhorn API. Data: %s", data);
|
||||
}
|
||||
|
||||
if (status !== 200) {
|
||||
logger.error("HTTP %d getting data from Longhorn API. Data: %s", status, data);
|
||||
}
|
||||
|
||||
if (contentType) res.setHeader("Content-Type", contentType);
|
||||
|
||||
const nodes = parseLonghornData(data);
|
||||
|
||||
return res.status(200).json({
|
||||
nodes,
|
||||
});
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/conf
|
||||
import ErrorBoundary from "components/errorboundry";
|
||||
import themes from "utils/styles/themes";
|
||||
import QuickLaunch from "components/quicklaunch";
|
||||
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
|
||||
|
||||
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
|
||||
ssr: false,
|
||||
@@ -99,7 +100,7 @@ function Index({ initialSettings, fallback }) {
|
||||
localStorage.setItem("hash", hashData.hash);
|
||||
}
|
||||
|
||||
if (previousHash && previousHash !== hashData.hash) {
|
||||
if (!initialSettings.isValid || (previousHash && previousHash !== hashData.hash)) {
|
||||
setStale(true);
|
||||
localStorage.setItem("hash", hashData.hash);
|
||||
|
||||
@@ -111,7 +112,7 @@ function Index({ initialSettings, fallback }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [hashData]);
|
||||
}, [hashData, initialSettings]);
|
||||
|
||||
if (stale) {
|
||||
return (
|
||||
@@ -193,6 +194,20 @@ function Home({ initialSettings }) {
|
||||
|
||||
const [searching, setSearching] = useState(false);
|
||||
const [searchString, setSearchString] = useState("");
|
||||
let searchProvider = null;
|
||||
const searchWidget = Object.values(widgets).find(w => w.type === "search");
|
||||
if (searchWidget) {
|
||||
if (Array.isArray(searchWidget.options?.provider)) {
|
||||
// if search provider is a list, try to retrieve from localstorage, fall back to the first
|
||||
searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]];
|
||||
} else if (searchWidget.options?.provider === 'custom') {
|
||||
searchProvider = {
|
||||
url: searchWidget.options.url
|
||||
}
|
||||
} else {
|
||||
searchProvider = searchProviders[searchWidget.options?.provider];
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
function handleKeyDown(e) {
|
||||
@@ -251,6 +266,7 @@ function Home({ initialSettings }) {
|
||||
isOpen={searching}
|
||||
close={setSearching}
|
||||
searchDescriptions={settings.quicklaunch?.searchDescriptions}
|
||||
searchProvider={settings.quicklaunch?.hideInternetSearch ? null : searchProvider}
|
||||
/>
|
||||
{widgets && (
|
||||
<>
|
||||
|
||||
2
src/skeleton/kubernetes.yaml
Normal file
2
src/skeleton/kubernetes.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
# sample kubernetes config
|
||||
3
src/styles/custom.css
Normal file
3
src/styles/custom.css
Normal file
@@ -0,0 +1,3 @@
|
||||
/*
|
||||
Mount this file and define your custom styles
|
||||
*/
|
||||
@@ -5,9 +5,25 @@ import path from "path";
|
||||
import yaml from "js-yaml";
|
||||
|
||||
import checkAndCopyConfig, { getSettings } from "utils/config/config";
|
||||
import { servicesFromConfig, servicesFromDocker, cleanServiceGroups } from "utils/config/service-helpers";
|
||||
import {
|
||||
servicesFromConfig,
|
||||
servicesFromDocker,
|
||||
cleanServiceGroups,
|
||||
servicesFromKubernetes
|
||||
} from "utils/config/service-helpers";
|
||||
import { cleanWidgetGroups, widgetsFromConfig } from "utils/config/widget-helpers";
|
||||
|
||||
/**
|
||||
* Compares services by weight then by name.
|
||||
*/
|
||||
function compareServices(service1, service2) {
|
||||
const comp = service1.weight - service2.weight;
|
||||
if (comp !== 0) {
|
||||
return comp;
|
||||
}
|
||||
return service1.name.localeCompare(service2.name);
|
||||
}
|
||||
|
||||
export async function bookmarksResponse() {
|
||||
checkAndCopyConfig("bookmarks.yaml");
|
||||
|
||||
@@ -44,19 +60,28 @@ export async function widgetsResponse() {
|
||||
}
|
||||
|
||||
export async function servicesResponse() {
|
||||
let discoveredServices;
|
||||
let discoveredDockerServices;
|
||||
let discoveredKubernetesServices;
|
||||
let configuredServices;
|
||||
let initialSettings;
|
||||
|
||||
try {
|
||||
discoveredServices = cleanServiceGroups(await servicesFromDocker());
|
||||
if (discoveredServices?.length === 0) {
|
||||
discoveredDockerServices = cleanServiceGroups(await servicesFromDocker());
|
||||
if (discoveredDockerServices?.length === 0) {
|
||||
console.debug("No containers were found with homepage labels.");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to discover services, please check docker.yaml for errors or remove example entries.");
|
||||
if (e) console.error(e.toString());
|
||||
discoveredServices = [];
|
||||
discoveredDockerServices = [];
|
||||
}
|
||||
|
||||
try {
|
||||
discoveredKubernetesServices = cleanServiceGroups(await servicesFromKubernetes());
|
||||
} catch (e) {
|
||||
console.error("Failed to discover services, please check kubernetes.yaml for errors or remove example entries.");
|
||||
if (e) console.error(e.toString());
|
||||
discoveredKubernetesServices = [];
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -76,7 +101,11 @@ export async function servicesResponse() {
|
||||
}
|
||||
|
||||
const mergedGroupsNames = [
|
||||
...new Set([discoveredServices.map((group) => group.name), configuredServices.map((group) => group.name)].flat()),
|
||||
...new Set([
|
||||
discoveredDockerServices.map((group) => group.name),
|
||||
discoveredKubernetesServices.map((group) => group.name),
|
||||
configuredServices.map((group) => group.name),
|
||||
].flat()),
|
||||
];
|
||||
|
||||
const sortedGroups = [];
|
||||
@@ -84,12 +113,18 @@ export async function servicesResponse() {
|
||||
const definedLayouts = initialSettings.layout ? Object.keys(initialSettings.layout) : null;
|
||||
|
||||
mergedGroupsNames.forEach((groupName) => {
|
||||
const discoveredGroup = discoveredServices.find((group) => group.name === groupName) || { services: [] };
|
||||
const discoveredDockerGroup = discoveredDockerServices.find((group) => group.name === groupName) || { services: [] };
|
||||
const discoveredKubernetesGroup = discoveredKubernetesServices.find((group) => group.name === groupName) || { services: [] };
|
||||
const configuredGroup = configuredServices.find((group) => group.name === groupName) || { services: [] };
|
||||
|
||||
const mergedGroup = {
|
||||
name: groupName,
|
||||
services: [...discoveredGroup.services, ...configuredGroup.services].filter((service) => service),
|
||||
services: [
|
||||
...discoveredDockerGroup.services,
|
||||
...discoveredKubernetesGroup.services,
|
||||
...configuredGroup.services
|
||||
].filter((service) => service)
|
||||
.sort(compareServices),
|
||||
};
|
||||
|
||||
if (definedLayouts) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable no-console */
|
||||
import { join } from "path";
|
||||
import { existsSync, copyFile, readFileSync } from "fs";
|
||||
import { existsSync, copyFile, readFileSync, statSync } from "fs";
|
||||
|
||||
import yaml from "js-yaml";
|
||||
|
||||
@@ -32,5 +32,18 @@ export function getSettings() {
|
||||
|
||||
const settingsYaml = join(process.cwd(), "config", "settings.yaml");
|
||||
const fileContents = readFileSync(settingsYaml, "utf8");
|
||||
return yaml.load(fileContents) ?? {};
|
||||
|
||||
let stats;
|
||||
try {
|
||||
stats = statSync(settingsYaml);
|
||||
} catch (e) {
|
||||
stats = {};
|
||||
}
|
||||
|
||||
const yamlLoaded = yaml.load(fileContents) ?? {};
|
||||
|
||||
return {
|
||||
...yamlLoaded,
|
||||
isValid: fileContents !== "-\n" && stats.size !== 2 // see https://github.com/benphelps/homepage/pull/609
|
||||
};
|
||||
}
|
||||
30
src/utils/config/kubernetes.js
Normal file
30
src/utils/config/kubernetes.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import path from "path";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
import yaml from "js-yaml";
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
|
||||
import checkAndCopyConfig from "utils/config/config";
|
||||
|
||||
export default function getKubeConfig() {
|
||||
checkAndCopyConfig("kubernetes.yaml");
|
||||
|
||||
const configFile = path.join(process.cwd(), "config", "kubernetes.yaml");
|
||||
const configData = readFileSync(configFile, "utf8");
|
||||
const config = yaml.load(configData);
|
||||
const kc = new KubeConfig();
|
||||
|
||||
switch (config?.mode) {
|
||||
case 'cluster':
|
||||
kc.loadFromCluster();
|
||||
break;
|
||||
case 'default':
|
||||
kc.loadFromDefault();
|
||||
break;
|
||||
case 'disabled':
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return kc;
|
||||
}
|
||||
@@ -4,9 +4,14 @@ import path from "path";
|
||||
import yaml from "js-yaml";
|
||||
import Docker from "dockerode";
|
||||
import * as shvl from "shvl";
|
||||
import { NetworkingV1Api } from "@kubernetes/client-node";
|
||||
|
||||
import createLogger from "utils/logger";
|
||||
import checkAndCopyConfig from "utils/config/config";
|
||||
import getDockerArguments from "utils/config/docker";
|
||||
import getKubeConfig from "utils/config/kubernetes";
|
||||
|
||||
const logger = createLogger("service-helpers");
|
||||
|
||||
export async function servicesFromConfig() {
|
||||
checkAndCopyConfig("services.yaml");
|
||||
@@ -28,6 +33,15 @@ export async function servicesFromConfig() {
|
||||
})),
|
||||
}));
|
||||
|
||||
// add default weight to services based on their position in the configuration
|
||||
servicesArray.forEach((group, groupIndex) => {
|
||||
group.services.forEach((service, serviceIndex) => {
|
||||
if(!service.weight) {
|
||||
servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return servicesArray;
|
||||
}
|
||||
|
||||
@@ -108,11 +122,106 @@ export async function servicesFromDocker() {
|
||||
return mappedServiceGroups;
|
||||
}
|
||||
|
||||
function getUrlFromIngress(ingress) {
|
||||
const urlHost = ingress.spec.rules[0].host;
|
||||
const urlPath = ingress.spec.rules[0].http.paths[0].path;
|
||||
const urlSchema = ingress.spec.tls ? 'https' : 'http';
|
||||
return `${urlSchema}://${urlHost}${urlPath}`;
|
||||
}
|
||||
|
||||
export async function servicesFromKubernetes() {
|
||||
const ANNOTATION_BASE = 'gethomepage.dev';
|
||||
const ANNOTATION_WIDGET_BASE = `${ANNOTATION_BASE}/widget.`;
|
||||
const ANNOTATION_POD_SELECTOR = `${ANNOTATION_BASE}/pod-selector`;
|
||||
|
||||
checkAndCopyConfig("kubernetes.yaml");
|
||||
|
||||
try {
|
||||
const kc = getKubeConfig();
|
||||
if (!kc) {
|
||||
return [];
|
||||
}
|
||||
const networking = kc.makeApiClient(NetworkingV1Api);
|
||||
|
||||
const ingressList = await networking.listIngressForAllNamespaces(null, null, null, null)
|
||||
.then((response) => response.body)
|
||||
.catch((error) => {
|
||||
logger.error("Error getting ingresses: %d %s %s", error.statusCode, error.body, error.response);
|
||||
return null;
|
||||
});
|
||||
if (!ingressList) {
|
||||
return [];
|
||||
}
|
||||
const services = ingressList.items
|
||||
.filter((ingress) => ingress.metadata.annotations && ingress.metadata.annotations[`${ANNOTATION_BASE}/enabled`] === 'true')
|
||||
.map((ingress) => {
|
||||
const constructedService = {
|
||||
app: ingress.metadata.name,
|
||||
namespace: ingress.metadata.namespace,
|
||||
href: ingress.metadata.annotations[`${ANNOTATION_BASE}/href`] || getUrlFromIngress(ingress),
|
||||
name: ingress.metadata.annotations[`${ANNOTATION_BASE}/name`] || ingress.metadata.name,
|
||||
group: ingress.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
|
||||
weight: ingress.metadata.annotations[`${ANNOTATION_BASE}/weight`] || '0',
|
||||
icon: ingress.metadata.annotations[`${ANNOTATION_BASE}/icon`] || '',
|
||||
description: ingress.metadata.annotations[`${ANNOTATION_BASE}/description`] || '',
|
||||
};
|
||||
if (ingress.metadata.annotations[ANNOTATION_POD_SELECTOR]) {
|
||||
constructedService.podSelector = ingress.metadata.annotations[ANNOTATION_POD_SELECTOR];
|
||||
}
|
||||
Object.keys(ingress.metadata.annotations).forEach((annotation) => {
|
||||
if (annotation.startsWith(ANNOTATION_WIDGET_BASE)) {
|
||||
shvl.set(constructedService, annotation.replace(`${ANNOTATION_BASE}/`, ""), ingress.metadata.annotations[annotation]);
|
||||
}
|
||||
});
|
||||
|
||||
return constructedService;
|
||||
});
|
||||
|
||||
const mappedServiceGroups = [];
|
||||
|
||||
services.forEach((serverService) => {
|
||||
let serverGroup = mappedServiceGroups.find((searchedGroup) => searchedGroup.name === serverService.group);
|
||||
if (!serverGroup) {
|
||||
mappedServiceGroups.push({
|
||||
name: serverService.group,
|
||||
services: [],
|
||||
});
|
||||
serverGroup = mappedServiceGroups[mappedServiceGroups.length - 1];
|
||||
}
|
||||
|
||||
const { name: serviceName, group: serverServiceGroup, ...pushedService } = serverService;
|
||||
const result = {
|
||||
name: serviceName,
|
||||
...pushedService,
|
||||
};
|
||||
|
||||
serverGroup.services.push(result);
|
||||
});
|
||||
|
||||
return mappedServiceGroups;
|
||||
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export function cleanServiceGroups(groups) {
|
||||
return groups.map((serviceGroup) => ({
|
||||
name: serviceGroup.name,
|
||||
services: serviceGroup.services.map((service) => {
|
||||
const cleanedService = { ...service };
|
||||
if (typeof service.weight === 'string') {
|
||||
const weight = parseInt(service.weight, 10);
|
||||
if (Number.isNaN(weight)) {
|
||||
cleanedService.weight = 0;
|
||||
} else {
|
||||
cleanedService.weight = weight;
|
||||
}
|
||||
}
|
||||
if (typeof cleanedService.weight !== "number") {
|
||||
cleanedService.weight = 0;
|
||||
}
|
||||
|
||||
if (cleanedService.widget) {
|
||||
// whitelisted set of keys to pass to the frontend
|
||||
@@ -123,12 +232,18 @@ export function cleanServiceGroups(groups) {
|
||||
container,
|
||||
currency, // coinmarketcap widget
|
||||
symbols,
|
||||
defaultinterval
|
||||
defaultinterval,
|
||||
namespace, // kubernetes widget
|
||||
app,
|
||||
podSelector,
|
||||
wan // opnsense widget
|
||||
} = cleanedService.widget;
|
||||
|
||||
const fieldsList = typeof fields === 'string' ? JSON.parse(fields) : fields;
|
||||
|
||||
cleanedService.widget = {
|
||||
type,
|
||||
fields: fields || null,
|
||||
fields: fieldsList || null,
|
||||
service_name: service.name,
|
||||
service_group: serviceGroup.name,
|
||||
};
|
||||
@@ -141,6 +256,14 @@ export function cleanServiceGroups(groups) {
|
||||
if (server) cleanedService.widget.server = server;
|
||||
if (container) cleanedService.widget.container = container;
|
||||
}
|
||||
if (type === "kubernetes") {
|
||||
if (namespace) cleanedService.widget.namespace = namespace;
|
||||
if (app) cleanedService.widget.app = app;
|
||||
if (podSelector) cleanedService.widget.podSelector = podSelector;
|
||||
}
|
||||
if (type === "opnsense") {
|
||||
if (wan) cleanedService.widget.wan = wan;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanedService;
|
||||
@@ -171,5 +294,15 @@ export default async function getServiceWidget(group, service) {
|
||||
}
|
||||
}
|
||||
|
||||
const kubernetesServices = await servicesFromKubernetes();
|
||||
const kubernetesServiceGroup = kubernetesServices.find((g) => g.name === group);
|
||||
if (kubernetesServiceGroup) {
|
||||
const kubernetesServiceEntry = kubernetesServiceGroup.services.find((s) => s.name === service);
|
||||
if (kubernetesServiceEntry) {
|
||||
const { widget } = kubernetesServiceEntry;
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
45
src/utils/kubernetes/kubernetes-utils.js
Normal file
45
src/utils/kubernetes/kubernetes-utils.js
Normal file
@@ -0,0 +1,45 @@
|
||||
export function parseCpu(cpuStr) {
|
||||
const unitLength = 1;
|
||||
const base = Number.parseInt(cpuStr, 10);
|
||||
const units = cpuStr.substring(cpuStr.length - unitLength);
|
||||
if (Number.isNaN(Number(units))) {
|
||||
switch (units) {
|
||||
case 'n':
|
||||
return base / 1000000000;
|
||||
case 'u':
|
||||
return base / 1000000;
|
||||
case 'm':
|
||||
return base / 1000;
|
||||
default:
|
||||
return base;
|
||||
}
|
||||
} else {
|
||||
return Number.parseInt(cpuStr, 10);
|
||||
}
|
||||
}
|
||||
|
||||
export function parseMemory(memStr) {
|
||||
const unitLength = (memStr.substring(memStr.length - 1) === 'i' ? 2 : 1);
|
||||
const base = Number.parseInt(memStr, 10);
|
||||
const units = memStr.substring(memStr.length - unitLength);
|
||||
if (Number.isNaN(Number(units))) {
|
||||
switch (units) {
|
||||
case 'Ki':
|
||||
return base * 1000;
|
||||
case 'K':
|
||||
return base * 1024;
|
||||
case 'Mi':
|
||||
return base * 1000000;
|
||||
case 'M':
|
||||
return base * 1024 * 1024;
|
||||
case 'Gi':
|
||||
return base * 1000000000;
|
||||
case 'G':
|
||||
return base * 1024 * 1024 * 1024;
|
||||
default:
|
||||
return base;
|
||||
}
|
||||
} else {
|
||||
return Number.parseInt(memStr, 10);
|
||||
}
|
||||
}
|
||||
@@ -34,12 +34,18 @@ export default async function credentialedProxyHandler(req, res, map) {
|
||||
headers.Authorization = `Bearer ${widget.key}`;
|
||||
} else if (widget.type === "proxmox") {
|
||||
headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`;
|
||||
} else if (widget.type === "proxmoxbackupserver") {
|
||||
delete headers["Content-Type"];
|
||||
headers.Authorization = `PBSAPIToken=${widget.username}:${widget.password}`;
|
||||
} else if (widget.type === "autobrr") {
|
||||
headers["X-API-Token"] = `${widget.key}`;
|
||||
} else if (widget.type === "tubearchivist") {
|
||||
headers.Authorization = `Token ${widget.key}`;
|
||||
} else if (widget.type === "miniflux") {
|
||||
headers["X-Auth-Token"] = `${widget.key}`;
|
||||
} else if (widget.type === "cloudflared") {
|
||||
headers["X-Auth-Email"] = `${widget.email}`;
|
||||
headers["X-Auth-Key"] = `${widget.key}`;
|
||||
} else {
|
||||
headers["X-API-Key"] = `${widget.key}`;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import { formatProxyUrl } from "./api-helpers";
|
||||
|
||||
export default function useWidgetAPI(widget, ...options) {
|
||||
const config = {};
|
||||
if (options?.refreshInterval) {
|
||||
config.refreshInterval = options.refreshInterval;
|
||||
if (options && options[1]?.refreshInterval) {
|
||||
config.refreshInterval = options[1].refreshInterval;
|
||||
}
|
||||
const { data, error } = useSWR(formatProxyUrl(widget, ...options), config);
|
||||
// make the data error the top-level error
|
||||
|
||||
31
src/widgets/cloudflared/component.jsx
Normal file
31
src/widgets/cloudflared/component.jsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "cfd_tunnel");
|
||||
|
||||
if (statsError) {
|
||||
return <Container error={statsError} />;
|
||||
}
|
||||
|
||||
if (!statsData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="cloudflared.status" />
|
||||
<Block label="cloudflared.origin_ip" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const originIP = statsData.result.connections?.origin_ip ?? statsData.result.connections[0]?.origin_ip;
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="cloudflared.status" value={statsData.result.status.charAt(0).toUpperCase() + statsData.result.status.slice(1)} />
|
||||
<Block label="cloudflared.origin_ip" value={originIP} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
18
src/widgets/cloudflared/widget.js
Normal file
18
src/widgets/cloudflared/widget.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const widget = {
|
||||
api: "https://api.cloudflare.com/client/v4/accounts/{accountid}/{endpoint}/{tunnelid}",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
|
||||
mappings: {
|
||||
"cfd_tunnel": {
|
||||
endpoint: "cfd_tunnel",
|
||||
validate: [
|
||||
"success",
|
||||
"result"
|
||||
]
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -6,10 +6,12 @@ const components = {
|
||||
autobrr: dynamic(() => import("./autobrr/component")),
|
||||
bazarr: dynamic(() => import("./bazarr/component")),
|
||||
changedetectionio: dynamic(() => import("./changedetectionio/component")),
|
||||
cloudflared: dynamic(() => import("./cloudflared/component")),
|
||||
coinmarketcap: dynamic(() => import("./coinmarketcap/component")),
|
||||
deluge: dynamic(() => import("./deluge/component")),
|
||||
downloadstation: dynamic(() => import("./downloadstation/component")),
|
||||
docker: dynamic(() => import("./docker/component")),
|
||||
kubernetes: dynamic(() => import("./kubernetes/component")),
|
||||
emby: dynamic(() => import("./emby/component")),
|
||||
flood: dynamic(() => import("./flood/component")),
|
||||
gluetun: dynamic(() => import("./gluetun/component")),
|
||||
@@ -21,17 +23,21 @@ const components = {
|
||||
jellyseerr: dynamic(() => import("./jellyseerr/component")),
|
||||
lidarr: dynamic(() => import("./lidarr/component")),
|
||||
mastodon: dynamic(() => import("./mastodon/component")),
|
||||
medusa: dynamic(() => import("./medusa/component")),
|
||||
miniflux: dynamic(() => import("./miniflux/component")),
|
||||
mikrotik: dynamic(() => import("./mikrotik/component")),
|
||||
moonraker: dynamic(() => import("./moonraker/component")),
|
||||
navidrome: dynamic(() => import("./navidrome/component")),
|
||||
nextdns: dynamic(() => import("./nextdns/component")),
|
||||
npm: dynamic(() => import("./npm/component")),
|
||||
nzbget: dynamic(() => import("./nzbget/component")),
|
||||
octoprint: dynamic(() => import("./octoprint/component")),
|
||||
omada: dynamic(() => import("./omada/component")),
|
||||
ombi: dynamic(() => import("./ombi/component")),
|
||||
opnsense: dynamic(() => import("./opnsense/component")),
|
||||
overseerr: dynamic(() => import("./overseerr/component")),
|
||||
paperlessngx: dynamic(() => import("./paperlessngx/component")),
|
||||
proxmoxbackupserver: dynamic(() => import("./proxmoxbackupserver/component")),
|
||||
pihole: dynamic(() => import("./pihole/component")),
|
||||
plex: dynamic(() => import("./plex/component")),
|
||||
portainer: dynamic(() => import("./portainer/component")),
|
||||
@@ -56,6 +62,8 @@ const components = {
|
||||
unifi: dynamic(() => import("./unifi/component")),
|
||||
watchtower: dynamic(() => import("./watchtower/component")),
|
||||
xteve: dynamic(() => import("./xteve/component")),
|
||||
immich: dynamic(() => import("./immich/component")),
|
||||
uptimekuma: dynamic(() => import("./uptimekuma/component")),
|
||||
};
|
||||
|
||||
export default components;
|
||||
|
||||
33
src/widgets/immich/component.jsx
Normal file
33
src/widgets/immich/component.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
const { data: immichData, error: immichError } = useWidgetAPI(widget);
|
||||
|
||||
if (immichError || immichData?.statusCode === 401) {
|
||||
return <Container error={immichError ?? immichData} />;
|
||||
}
|
||||
|
||||
if (!immichData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="immich.users" />
|
||||
<Block label="immich.photos" />
|
||||
<Block label="immich.videos" />
|
||||
<Block label="immich.storage" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="immich.users" value={immichData.usageByUser.length} />
|
||||
<Block label="immich.photos" value={immichData.photos} />
|
||||
<Block label="immich.videos" value={immichData.videos} />
|
||||
<Block label="immich.storage" value={immichData.usage} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
8
src/widgets/immich/widget.js
Normal file
8
src/widgets/immich/widget.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/server-info/stats",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
};
|
||||
|
||||
export default widget;
|
||||
50
src/widgets/kubernetes/component.jsx
Normal file
50
src/widgets/kubernetes/component.jsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
const podSelectorString = widget.podSelector !== undefined ? `podSelector=${widget.podSelector}` : "";
|
||||
const { data: statusData, error: statusError } = useSWR(
|
||||
`/api/kubernetes/status/${widget.namespace}/${widget.app}?${podSelectorString}`);
|
||||
|
||||
const { data: statsData, error: statsError } = useSWR(
|
||||
`/api/kubernetes/stats/${widget.namespace}/${widget.app}?${podSelectorString}`);
|
||||
|
||||
if (statsError || statusError) {
|
||||
return <Container error={t("widget.api_error")} />;
|
||||
}
|
||||
|
||||
if (statusData && statusData.status !== "running") {
|
||||
return (
|
||||
<Container>
|
||||
<Block label={t("widget.status")} value={t("docker.offline")} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
if (!statsData || !statusData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="docker.cpu" />
|
||||
<Block label="docker.mem" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
{statsData.stats.cpuLimit && (
|
||||
<Block label="docker.cpu" value={t("common.percent", { value: statsData.stats.cpuUsage })} />
|
||||
) || (
|
||||
<Block label="docker.cpu" value={t("common.number", { value: statsData.stats.cpu, maximumFractionDigits: 4 })}
|
||||
/>
|
||||
)}
|
||||
<Block label="docker.mem" value={t("common.bytes", { value: statsData.stats.mem })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
39
src/widgets/medusa/component.jsx
Normal file
39
src/widgets/medusa/component.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
const { widget } = service;
|
||||
|
||||
const { data: statsData, error: statsError } = useWidgetAPI(widget, "stats");
|
||||
const { data: futureData, error: futureError } = useWidgetAPI(widget, "future");
|
||||
|
||||
if (statsError || futureError) {
|
||||
const finalError = statsError ?? futureError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!statsData || !futureData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="medusa.wanted" />
|
||||
<Block label="medusa.queued" />
|
||||
<Block label="medusa.series" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const { later, missed, soon, today } = futureData.data;
|
||||
const future = later.length + missed.length + soon.length + today.length;
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="medusa.wanted" value={t("common.number", { value: future })} />
|
||||
<Block label="medusa.queued" value={t("common.number", { value: statsData.data.ep_snatched })} />
|
||||
<Block label="medusa.series" value={t("common.number", { value: statsData.data.shows_active })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
23
src/widgets/medusa/widget.js
Normal file
23
src/widgets/medusa/widget.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/v1/{key}/{endpoint}/",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
stats: {
|
||||
endpoint: "?cmd=shows.stats",
|
||||
validate: [
|
||||
"data"
|
||||
]
|
||||
},
|
||||
future: {
|
||||
endpoint: "?cmd=future",
|
||||
validate: [
|
||||
"data"
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default widget;
|
||||
51
src/widgets/moonraker/component.jsx
Normal file
51
src/widgets/moonraker/component.jsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: printStats, error: printStatsError } = useWidgetAPI(widget, "print_stats");
|
||||
const { data: displayStatus, error: displayStatsError } = useWidgetAPI(widget, "display_status");
|
||||
const { data: webHooks, error: webHooksError } = useWidgetAPI(widget, "webhooks");
|
||||
|
||||
if (printStatsError || displayStatsError || webHooksError) {
|
||||
const finalError = printStatsError ?? displayStatsError ?? webHooksError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!printStats || !displayStatus || !webHooks) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="moonraker.printer_state" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
if (webHooks.result.status.webhooks.state === "shutdown") {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="moonraker.printer_state" value={webHooks.result.status.webhooks.state} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
let currentLayer = "-";
|
||||
let totalLayer = "-";
|
||||
if (printStats.result.status.print_stats.info.total_layer !== null) {
|
||||
currentLayer = printStats.result.status.print_stats.info.current_layer;
|
||||
totalLayer = printStats.result.status.print_stats.info.total_layer;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="moonraker.layers" value={`${currentLayer} / ${totalLayer}`} />
|
||||
<Block label="moonraker.print_progress" value={t("common.percent", { value: (displayStatus.result.status.display_status.progress * 100) })} />
|
||||
<Block label="moonraker.print_status" value={printStats.result.status.print_stats.state} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
20
src/widgets/moonraker/widget.js
Normal file
20
src/widgets/moonraker/widget.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/printer/objects/query?{endpoint}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
print_stats: {
|
||||
endpoint: "print_stats",
|
||||
},
|
||||
display_status: {
|
||||
endpoint: "display_status",
|
||||
},
|
||||
webhooks: {
|
||||
endpoint: "webhooks",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -27,7 +27,7 @@ export default function Component({ service }) {
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="nzbget.rate" value={t("common.bitrate", { value: statusData.DownloadRate })} />
|
||||
<Block label="nzbget.rate" value={t("common.byterate", { value: statusData.DownloadRate })} />
|
||||
<Block
|
||||
label="nzbget.remaining"
|
||||
value={t("common.bytes", { value: statusData.RemainingSizeMB * 1024 * 1024 })}
|
||||
|
||||
64
src/widgets/octoprint/component.jsx
Normal file
64
src/widgets/octoprint/component.jsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { widget } = service;
|
||||
|
||||
const { data: printerStats, error: printerStatsError } = useWidgetAPI(widget, "printer_stats");
|
||||
const { data: jobStats, error: jobStatsError } = useWidgetAPI(widget, "job_stats");
|
||||
|
||||
if (printerStatsError) {
|
||||
return <Container error={printerStatsError} />;
|
||||
}
|
||||
|
||||
if (jobStatsError) {
|
||||
return <Container error={jobStatsError} />;
|
||||
}
|
||||
|
||||
const state = printerStats?.state?.text;
|
||||
const tempTool = printerStats?.temperature?.tool0?.actual;
|
||||
const tempBed = printerStats?.temperature?.bed?.actual;
|
||||
|
||||
if (!printerStats || !state || !tempTool || !tempBed) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="octoprint.printer_state" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const printingStateFalgs = ["Printing", "Paused", "Pausing", "Resuming"];
|
||||
|
||||
if (printingStateFalgs.includes(state)) {
|
||||
const { completion } = jobStats.progress;
|
||||
|
||||
if (!jobStats || !completion) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="octoprint.printer_state" />
|
||||
<Block label="octoprint.temp_tool" />
|
||||
<Block label="octoprint.temp_bed" />
|
||||
<Block label="octoprint.job_completion" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="octoprint.printer_state" value={printerStats.state.text} />
|
||||
<Block label="octoprint.temp_tool" value={`${printerStats.temperature.tool0.actual} °C`} />
|
||||
<Block label="octoprint.temp_bed" value={`${printerStats.temperature.bed.actual} °C`} />
|
||||
<Block label="octoprint.job_completion" value={`${completion.toFixed(2)}%`} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="octoprint.printer_state" value={printerStats.state.text} />
|
||||
<Block label="octoprint.temp_tool" value={`${printerStats.temperature.tool0.actual} °C`} />
|
||||
<Block label="octoprint.temp_bed" value={`${printerStats.temperature.bed.actual} °C`} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
17
src/widgets/octoprint/widget.js
Normal file
17
src/widgets/octoprint/widget.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import genericProxyHandler from "utils/proxy/handlers/generic";
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api/{endpoint}?apikey={key}",
|
||||
proxyHandler: genericProxyHandler,
|
||||
|
||||
mappings: {
|
||||
printer_stats: {
|
||||
endpoint: "printer",
|
||||
},
|
||||
job_stats: {
|
||||
endpoint: "job",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
@@ -33,16 +33,14 @@ export default function Component({ service }) {
|
||||
const cpu = 100 - parseFloat(cpuIdle);
|
||||
const memory = activityData.headers[3].match(/Mem: (.+) Active,/)[1];
|
||||
|
||||
const wanUpload = interfaceData.interfaces.wan['bytes transmitted'];
|
||||
const wanDownload = interfaceData.interfaces.wan['bytes received'];
|
||||
const wan = widget.wan ? interfaceData.interfaces[widget.wan] : interfaceData.interfaces.wan;
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="opnsense.cpu" value={t("common.percent", { value: cpu.toFixed(2) })} />
|
||||
<Block label="opnsense.memory" value={memory} />
|
||||
<Block label="opnsense.wanUpload" value={t("common.bytes", { value: wanUpload })} />
|
||||
<Block label="opnsense.wanDownload" value={t("common.bytes", { value: wanDownload })} />
|
||||
|
||||
{wan && <Block label="opnsense.wanUpload" value={t("common.bytes", { value: wan['bytes transmitted'] })} />}
|
||||
{wan && <Block label="opnsense.wanDownload" value={t("common.bytes", { value: wan['bytes received'] })} />}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ export default function Component({ service }) {
|
||||
}
|
||||
|
||||
const { data } = clusterData ;
|
||||
const vms = data.filter(item => item.type === "qemu") || [];
|
||||
const lxc = data.filter(item => item.type === "lxc") || [];
|
||||
const vms = data.filter(item => item.type === "qemu" && item.template === 0) || [];
|
||||
const lxc = data.filter(item => item.type === "lxc" && item.template === 0) || [];
|
||||
const nodes = data.filter(item => item.type === "node") || [];
|
||||
|
||||
const runningVMs = vms.reduce(calcRunning, 0);
|
||||
|
||||
45
src/widgets/proxmoxbackupserver/component.jsx
Normal file
45
src/widgets/proxmoxbackupserver/component.jsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
import Container from "components/services/widget/container";
|
||||
import Block from "components/services/widget/block";
|
||||
import useWidgetAPI from "utils/proxy/use-widget-api";
|
||||
|
||||
export default function Component({ service }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { widget } = service;
|
||||
|
||||
const { data: datastoreData, error: datastoreError } = useWidgetAPI(widget, "status/datastore-usage");
|
||||
const { data: tasksData, error: tasksError } = useWidgetAPI(widget, "nodes/localhost/tasks");
|
||||
const { data: hostData, error: hostError } = useWidgetAPI(widget, "nodes/localhost/status");
|
||||
|
||||
if (datastoreError || tasksError || hostError) {
|
||||
const finalError = tasksError ?? datastoreError ?? hostError;
|
||||
return <Container error={finalError} />;
|
||||
}
|
||||
|
||||
if (!datastoreData || !tasksData || !hostData) {
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="proxmoxbackupserver.datastore_usage" />
|
||||
<Block label="proxmoxbackupserver.failed_tasks" />
|
||||
<Block label="proxmoxbackupserver.cpu_usage" />
|
||||
<Block label="proxmoxbackupserver.memory_usage" />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const datastoreUsage = datastoreData.data[0].used / datastoreData.data[0].total * 100;
|
||||
const cpuUsage = hostData.data.cpu * 100;
|
||||
const memoryUsage = hostData.data.memory.used / hostData.data.memory.total * 100;
|
||||
const failedTasks = tasksData.total >= 100 ? "99+" : tasksData.total;
|
||||
|
||||
return (
|
||||
<Container service={service}>
|
||||
<Block label="proxmoxbackupserver.datastore_usage" value={t("common.percent", { value: datastoreUsage })} />
|
||||
<Block label="proxmoxbackupserver.failed_tasks_24h" value={failedTasks} />
|
||||
<Block label="proxmoxbackupserver.cpu_usage" value={t("common.percent", { value: cpuUsage })} />
|
||||
<Block label="proxmoxbackupserver.memory_usage" value={t("common.percent", { value: memoryUsage })} />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
22
src/widgets/proxmoxbackupserver/widget.js
Normal file
22
src/widgets/proxmoxbackupserver/widget.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
|
||||
|
||||
const since = Date.now() - (24 * 60 * 60 * 1000);
|
||||
|
||||
const widget = {
|
||||
api: "{url}/api2/json/{endpoint}",
|
||||
proxyHandler: credentialedProxyHandler,
|
||||
|
||||
mappings: {
|
||||
"status/datastore-usage": {
|
||||
endpoint: "status/datastore-usage",
|
||||
},
|
||||
"nodes/localhost/tasks": {
|
||||
endpoint: `nodes/localhost/tasks?errors=true&limit=100&since=${since}`,
|
||||
},
|
||||
"nodes/localhost/status": {
|
||||
endpoint: "nodes/localhost/status",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default widget;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user